How to load Multiple Sprites by name in Unity?

This is an open to suggestions tutorial. Meaning, this is just one way that I’m doing it, if you have any suggestions, please please leave a comment.

It’s funny, I’ve asked this question on Twitter, I Google-d and even asked this guy from a Unity group on Facebook, and either they didn’t understand my question or they didn’t really give me the answer I wanted. Is it because I am thinking in the wrong way and we actually don’t need to do this?

Anyway, someone suggested that I just grab by the index of the “child” sprite in the multiple sprite… but I wouldn’t know what that index is, because this is not for animation, this is just simply treating a Multiple Sprite as a spritesheet.

Oh by the way, I used the awesome TexturePacker and its super useful TexturePackerImporter script to slice the Multiple Sprite in Unity.

So my Multiple Sprite is automatically sliced:

Screen Shot 2014-05-26 at 12.13.07 PM

I mean, sure I can drag the sliced sprites individually into my Scene, but did you know that if you try to use Resources.Load to well, load them by name, it wouldn’t work? And if you are going to suggest why don’t I just create each child as prefabs first, or… I have my reasons for needing Resources.Load.

For example:

GameObject bg1 = GUIMgr.getSpriteObject(Resources.Load<Sprite>(Sprites/Rewards/rewards_bg-iphone4));

or

GameObject bg1 = GUIMgr.getSpriteObject(Resources.Load<Sprite>(Sprites/rewards_bg-iphone4));

Those are going to return a NullReference.

 

By the way GUIMgr.getSpriteObject is just a helper method I have to return a Sprite as a GameObject that is added in the Scene:

public static GameObject getSpriteObject(Spritesprite)
{    
GameObjectspriteObj = new GameObject();

    spriteObj.name = icon.name;
       
    spriteObj.AddComponent<SpriteRenderer>();
    SpriteRenderer spriteRenderer = spriteObj.GetComponent<SpriteRenderer>();
    spriteRenderer.sprite = sprite;

    return spriteObj;
}

 

Anyway, so I decided to do this instead, a Singleton named ResourceMgr:

using UnityEngine;
using System.Collections;

public class ResourceMgr : MonoBehaviour 
{
    private Hashtable m_sprites;

    #region Singleton
    private static ResourceMgr instance = null;
    public static ResourceMgr I
    {    get
        {    if (instance == null)
            {    GameObject resourceMgr = new GameObject();
                resourceMgr.name = ResourceMgr;
                resourceMgr.AddComponent<ResourceMgr>();

                resourceMgr.transform.position = Camera.main.transform.position;
            }
            return instance;
        }
    }
    public static bool HasInstance
    {    get
        {    return (instance != null);
        }
    }
    #endregion

    void Awake()
    {    if (instance == null)
        {    instance = this;

            // ResourceMgr is loaded per scene to avoid keeping too much in memory
        }
    }

    // spritsheet needs to be initialized first and foremost
    // initSpritesheet only accepts Multiple sprites
    public void initSpritesheet(Sprite[] spritesheet)
    {    
        if (m_sprites == null
        {    m_sprites = new Hashtable();        
        }

        foreach (Sprite sprite in spritesheet
        {    
            // sprites with same names are ignored
            if(!m_sprites.Contains(sprite.name))
            {    m_sprites.Add(sprite.namesprite);
            }
        }
    }

    public Sprite getSprite(string name)
    {    
        if (m_sprites.Contains (name)) 
        {    return (Spritem_sprites[name];        
        }

        return null;
    }
}

 

And this is how you use it:

using UnityEngine;
using System.Collections;

public class ResourcesTest : MonoBehaviour 
{
    public string[] m_filenames;

    void Start () 
    {    
        if(m_filenames != null)
        {    
            foreach(string filename in m_filenames)
            {    
                Sprite[] sprites = Resources.LoadAll<Sprite>(Sprites/ + filename);
                ResourceMgr.I.initSpritesheet(sprites);
            }
        }

        GameObject bg = GUIMgr.getSpriteObject(ResourceMgr.I.getSprite(rewards_bg-iphone4));
    }
}

 

Just load up m_filenames with the filenames of the spritesheets, such as Rewards.

And voila! (Maybe I should combine the getSpriteObject with getSprite. Yup, I’ll do that.)

Comments, suggestions, violent reactions, just tweet me @purplelilgirl.

Texture Packer and Automator

Texture Packer has a command line tool, which means that you can run it as a shell script in Automator. This means that you can get sprites from the Automator and automatically build spritesheets using them.

Why would I want to do this? Why can’t i just use Texture Packer with all its lovely GUI?

Because well for me, I process the sprites first using Automator, before I pack them into spritesheets. Also this is a quick way to not set all the different Texture Packer settings each time (yes, I know you can use Save Defaults for settings).

But double-clicking on my Automator app, and then select my sprites, and wait for it (it’s actually pretty quick) to automagically spit out spritesheets is still faster (and it only requires like 2 to 3 clicks), and it even supports multipack (in case the sprites doesn’t fit in just one spritesheet)

This is my (partial) Automator workflow:

Screen Shot 2014-05-08 at 11.31.15 AM
Screen Shot 2014-05-08 at 11.31.45 AM

A big shout out and thank you to Andreas Lowe for replying to all questions on Twitter, and helping me whip out that Shell Script.

This Automator app requires the Pro version of Texture Packer as well.

That’s it!

 

Sorry for not posting anything since creating this new blog in January, that’s because I temporarily moved back home (hello, Manila).