Certified studio & training center
ENFR
Lab

Unity - sprite packing

Best practices with Unity have always been an hidden gem. Most precisely concerning the Resources folder. Hopefully things are changing with Unity's best practices guide! And things are simple concerning the Resources…

Best practices with Unity have always been an hidden gem. Most precisely concerning the Resources folder. Hopefully things are changing with Unity’s best practices guide! And things are simple concerning the Resources folder: just don’t use it!

Managing 2D Sprites in Unity is simple if you have a static scene: just put every sprite needed on your screen and you’re almost done. Obviously you should package them in Spritesheets. The easy way to do it is via Unity’ Sprite Packer tool. But what to do if you need to load Sprites at runtime? How to access a Sprite if it’s not linked directly on a GameObject or a Prefab and without using the Resources folder?

Create a ScriptableObject! They are the best way to store informations within Unity. Here is an Editor Script for generating ScriptableObjects with a list of Sprites for each Packing Tag mentioned: [c-sharp] using UnityEngine; #if UNITY_EDITOR using UnityEditor; #endif using System; using System.Collections; using System.Collections.Generic; using System.IO;

[Serializable] public class SpritesData:ScriptableObject {

[SerializeField] public Sprite[] sprites;

static public string assetDirPath = “RuntimeSprites/SpritesData/”; static public string assetPath = “Assets/RuntimeSprites/SpritesData/{0}.asset”;

#if UNITY_EDITOR [MenuItem(“Data/Create Sprites Data”)] static void CreateSpritesData() { string dirPath = Application.dataPath + “/” + assetDirPath;

if (!System.IO.Directory.Exists(dirPath)) System.IO.Directory.CreateDirectory(@dirPath);

SpritesData data = ScriptableObject.CreateInstance();

List spritesList = new List();

string[] anims = AssetDatabase.FindAssets(“t:Sprite”, new string[] {“Assets/Sprites”});

string currentTag = “”;

foreach (string anim in anims) {

string path = AssetDatabase.GUIDToAssetPath(anim);

TextureImporter ti = TextureImporter.GetAtPath(path) as TextureImporter;

if (ti.spritePackingTag != currentTag) {

if (data && currentTag != “”) {

data.sprites = spritesList.ToArray(); AssetDatabase.CreateAsset(data, string.Format(assetPath, currentTag)); }

data = ScriptableObject.CreateInstance(); spritesList = new List();

currentTag = ti.spritePackingTag; }

Sprite sprite = AssetDatabase.LoadAssetAtPath(path);

spritesList.Add(sprite); }

data.sprites = spritesList.ToArray(); AssetDatabase.CreateAsset(data, string.Format(assetPath, currentTag)); } #endif } [/c-sharp]

Now that you have all your SpritesData you just have to create a MonoBehaviour with a public SpritesData[] spritesDatas; property, then you will have access to all your sprites! The good things is while a sprite isn’t displayed on Screen it’s not in memory.

Cheers!

AL
Aymeric Lamboley
Founder & CTO
// STAY IN TOUCH

Studio news,
straight to your inbox.

One email a month at most: our technical articles, project debriefs and new training sessions. No spam, one-click unsubscribe.