I’m trying to create an editor tool that will take a bunch of images (each a sprite sheet), slice them up, create animations from them, and create a controller override from a given template with all the right animations in all the right slots.
The idea is to quickly create animations for new characters without having to use the editor’s horrible pipeline (slice manually, drag and drop each group, setup the controllers, etc)
Right now I’m stuck in trying to slice the sprite from the editor script. Any ideas how to access the sprite editor or something similar from script?
I’m in a similar situation where I want to name a large sprite sheet through code. I started with this script here. In order to use these editor scripts you need to put them in a Editor folder. When you restart Unity you should see a Sprites menu at the top with “Rename Sprites” in the dropdown.
I modified it to slice the texture by a 16x16 grid, set the pivot, and then rename the sprites according to their index in the sprite sheet. The top left sprite is (0,0).
I hope this helps.
using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Collections.Generic;
public class NameSpritesAutomatically : MonoBehaviour {
[MenuItem("Sprites/Rename Sprites")]
static void SetSpriteNames()
{
Texture2D myTexture = (Texture2D)Resources.LoadAssetAtPath<Texture2D>("Assets/Sprites/MyTexture.png");
string path = AssetDatabase.GetAssetPath(myTexture);
TextureImporter ti = AssetImporter.GetAtPath(path) as TextureImporter;
ti.isReadable = true;
List<SpriteMetaData> newData = new List<SpriteMetaData>();
int SliceWidth = 16;
int SliceHeight = 16;
for (int i = 0; i < myTexture.width; i += SliceWidth)
{
for(int j = myTexture.height; j > 0; j -= SliceHeight)
{
SpriteMetaData smd = new SpriteMetaData();
smd.pivot = new Vector2(0.5f, 0.5f);
smd.alignment = 9;
smd.name = (myTexture.height - j)/SliceHeight + ", " + i/SliceWidth;
smd.rect = new Rect(i, j-SliceHeight, SliceWidth, SliceHeight);
newData.Add(smd);
}
}
ti.spritesheet = newData.ToArray();
AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);
}
}
This will give you a hotkey to automatically slice sprites just like using Sprite Editor > Slice > Automatic
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;
}
}
It will set the image asset automatically to be multiple sprites, saving you time setting it manually from “Single” to “Multiple” in the editor, and preventing a headache where you don’t know why the script isn’t working.,Add this line:
It will set the image asset automatically to be multiple sprites, saving you time setting it manually to multiple in the editor, and preventing a headache where you don’t know why the script isn’t working.