Skip to content

Instantly share code, notes, and snippets.

@shadesbelow
Last active April 8, 2024 04:24
Show Gist options
  • Save shadesbelow/8a6ddc54db795241f3cff539db6ea487 to your computer and use it in GitHub Desktop.
Save shadesbelow/8a6ddc54db795241f3cff539db6ea487 to your computer and use it in GitHub Desktop.
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditorInternal;
using UnityEngine;
// This is only useful for spritesheets that need to be automatically sliced (Sprite Editor > Slice > Automatic)
public class AutoSpriteSlicer
{
[MenuItem("Tools/Slice Spritesheets %&s")]
public static void Slice()
{
var textures = Selection.GetFiltered<Texture2D>(SelectionMode.Assets);
foreach (var texture in textures)
{
ProcessTexture(texture);
}
}
static void ProcessTexture(Texture2D texture)
{
string path = AssetDatabase.GetAssetPath(texture);
var importer = AssetImporter.GetAtPath(path) as TextureImporter;
//importer.isReadable = true;
importer.textureType = TextureImporterType.Sprite;
importer.spriteImportMode = SpriteImportMode.Multiple;
importer.mipmapEnabled = false;
importer.filterMode = FilterMode.Point;
importer.spritePivot = Vector2.down;
importer.textureCompression = TextureImporterCompression.Uncompressed;
var textureSettings = new TextureImporterSettings(); // need this stupid class because spriteExtrude and spriteMeshType aren't exposed on TextureImporter
importer.ReadTextureSettings(textureSettings);
textureSettings.spriteMeshType = SpriteMeshType.Tight;
textureSettings.spriteExtrude = 0;
importer.SetTextureSettings(textureSettings);
int minimumSpriteSize = 16;
int extrudeSize = 0;
Rect[] rects = InternalSpriteUtility.GenerateAutomaticSpriteRectangles(texture, minimumSpriteSize, extrudeSize);
var rectsList = new List<Rect>(rects);
rectsList = SortRects(rectsList, texture.width);
string filenameNoExtension = Path.GetFileNameWithoutExtension(path);
var metas = new List<SpriteMetaData>();
int rectNum = 0;
foreach (Rect rect in rectsList)
{
var meta = new SpriteMetaData();
meta.pivot = Vector2.down;
meta.alignment = (int)SpriteAlignment.BottomCenter;
meta.rect = rect;
meta.name = filenameNoExtension + "_" + rectNum++;
metas.Add(meta);
}
importer.spritesheet = metas.ToArray();
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
}
static List<Rect> SortRects(List<Rect> rects, float textureWidth)
{
List<Rect> list = new List<Rect>();
while (rects.Count > 0)
{
Rect rect = rects[rects.Count - 1];
Rect sweepRect = new Rect(0f, rect.yMin, textureWidth, rect.height);
List<Rect> list2 = RectSweep(rects, sweepRect);
if (list2.Count <= 0)
{
list.AddRange(rects);
break;
}
list.AddRange(list2);
}
return list;
}
static List<Rect> RectSweep(List<Rect> rects, Rect sweepRect)
{
List<Rect> result;
if (rects == null || rects.Count == 0)
{
result = new List<Rect>();
}
else
{
List<Rect> list = new List<Rect>();
foreach (Rect current in rects)
{
if (current.Overlaps(sweepRect))
{
list.Add(current);
}
}
foreach (Rect current2 in list)
{
rects.Remove(current2);
}
list.Sort((a, b) => a.x.CompareTo(b.x));
result = list;
}
return result;
}
}
@RampageRobot
Copy link

I'm really late to the party, but to answer RampageRobot's question, this line adds a method to the "Tools" Dropdown in the editor's toolbar: [MenuItem("Tools/Slice Spritesheets %&s")] image

Thank you!

@beilber
Copy link

beilber commented Oct 13, 2021

I found this while looking for a solution for my own problem with a script I wrote to do the same thing. I am curious if this behavior was encountered:
I have a sprite sheet that has what can best be described as "empty space", 7x7 grid of sprites, the last three sprites are just transparency (intentional, only 46 frames of animation)
So when my script and I would imagine this one is run, there would be three empty sprites generated. Would your script also have the same result?

@matkoniecz
Copy link

@shadesbelow Are you author of this code? Can you maybe specify license for it? Either by posting in comments here and for example declaring "It is MIT licensed" or by editing the code?

See https://choosealicense.com/

@stephenlucerne
Copy link

Editing TextureImporter.spritesheet no longer works in Unity 2020+
I shared a code snippet here (https://forum.unity.com/threads/sprite-editor-automatic-slicing-by-script.320776/#post-9756150) that works in newer versions of unity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment