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.

How to make animated sprites in Cocos2D? (using 3rd party sprites and TexturePacker)

First of all, thank you Andreas Loew for the TexturePacker and Physics Editor licenses.

This is not a tutorial per se, because a lot of information that I will include in this post are referenced from other people’s works, particularly Andreas’ (http://www.texturepacker.com/blog/).

So the question: How do we make animated sprites in Cocos2D using 3rd party sprites. I mentioned before TurboSquid as a good source for free 3D game assets, now I am telling you guys, that aside from free 3D game assets, a lot of 2D game assets are also available for free online, such as Reiner’s Tileset (all the assets that I’ll be using for is from Reiner’s Tileset).

So hop on over to Reiner’s Tileset, and find a character that you’d like, I picked this skeleton with a bow and arrow (he looks kind of cute).

Meet:

(no, I haven’t named him)

There are a lot of animations included for this character, there’s idle, talking, kicking… animations.

I will be using Andreas’ code (on the TexturePacker website) to load my sprites into the game (check out the blog post: Improved Sprite Loader). You can download the code from that blog post. The CCAnimate+SequenceLoader code loads a sequence of sprites with given format, the start index of sprite must begin with 1 (for example, sprite_0001.png sprite_0002.png, ….the format for this sequence would be “sprite_%04d.png”).

But, but the one from Reiner’s Tileset starts with 0, such as kicking_s0000… One idea is simply ignore the first frame (delete it). Okay, kidding, or rename every file. But what if the animation has like 60 frames?

Good thing, there’s an app called Better Finder Renamer, just drag the files you want to rename and then specifiy the prefix and the Starts with value. So, for our case, I specified “skeleton_kicking_00”, and starts with 1.

Next step, use TexturePacker to create our spritesheet. Click on Add Sprites and select the animation frame files. If you notice the sprite frames have a brown background (which we don’t actually need), Andreas talked about this in another blog post (Using TexturePacker with 3rd party assets).

So just remember to check:

Also check Trim sprite names, so the resulting plist will remove the file extensions of the sprite frames.

Okay, now that we have the the spritesheets ready, some code bits. Add to your project:

  • CCAnimate+SequenceLoader.h
  • CCAnimate+SequenceLoader.m
  • CCAnimation+SequenceLoader.h
  • CCAnimation+SequenceLoader.m

And then in your code, #import “CCAnimate+SequenceLoader.h”” (I placed this in the init of my scene), and then:

[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile: @”skeleton.plist”];
skeleton = [CCSprite spriteWithSpriteFrameName: @”skeleton_idle_s0001”];

CGSize size = [[CCDirector sharedDirector] winSize];        skeleton.position = ccp(size.width/2, size.height/2-10);
CCAnimate *animation = [CCAnimate actionWithSpriteSequence: @”skeleton_kicking_s%04d” delay: 0.1f restoreOriginalFrame: NO];
[skeleton runAction: [CCRepeatForever actionWithAction: animation]];
[self addChild: skeleton];

And then you are done! 🙂

You now have an animated skeleton in your game 🙂

Sources:

http://www.publicspace.net/ABetterFinderRename/

http://reinerstileset.4players.de/monstersE.html

http://www.texturepacker.com

http://www.texturepacker.com/2010/12/11/using-texturepacker-with-3rd-party-tile-sets/

http://www.texturepacker.com/2010/12/16/improved-sprite-loader/

http://www.code-and-web.de/downloads/AnimationSequenceLoader/1.0/AnimationSequenceLoader.zip