Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
September 22, 2018
arrowPress Releases
  • Editor-In-Chief:
    Kris Graft
  • Editor:
    Alex Wawro
  • Contributors:
    Chris Kerr
    Alissa McAloon
    Emma Kidwell
    Bryant Francis
    Katherine Cross
  • Advertising:
    Libby Kruse






If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 

Luckslinger tech #1 - How to make 2D Sprite Animations in Unity

by Donald Kooiker on 08/21/15 01:47:00 pm   Featured Blogs

1 comments Share on Twitter    RSS

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

So we've just released Luckslinger on Steam and some people were curious about the ‚Äėsystem‚Äô that we use for doing all the sprite-animations in the game. Actually the basics are quite simple, but after that it gets a bit more complicated. For this post I‚Äôll just go over the basics and explain how we use Unity‚Äôs Sprites to make simple(and later complex) 2D sprite animations.

Basically how it works is that, we make the animations in Graphicsgale and then export it as a full png. So that the whole animation is in one image. Then we import it in Unity as a¬†Sprite¬†with ‚ÄėMultiple‚Äô sprite mode, we then cut all the frames of the spritesheet correctly and filter as¬†point¬†and set the Format to¬†Truecolor.

We then create an ‚ÄėSpriteAnimation‚Äô in Unity and then add the ‚ÄėAnimation2D‚Äô component to it, we then add all the cut sprites in the array, do the settings, press Play in Unity and voila!

So how does this ‚ÄėAnimation2D‚Äô component work? We‚Äôll make it right now!

 So I’d say, create a new C# Class in your Unity project and call it Animation2D.

 First of all, we’ll need to add some settings to the Class.

public float FPS;
public bool isLooping;
public Sprite[] frames;
public bool playOnStartup = false;
private SpriteRenderer outputRenderer;
private float secondsToWait;

private int currentFrame;
private bool stopped = false;

Most of these variables are quite self-explanatory, you can set the FPS in the editor, set if it’s looping or not, set drag the correct frames for the animation and choose wether the animation will play when the scene loads. And the private variables are more for internal stuff.

So where do we go from here? Create an Awake function for your class (void Awake()) and it should look like this.

public void Awake () {


        outputRenderer = this.GetComponent<SpriteRenderer>();
            
        currentFrame = 0;
        if(FPS > 0) 
            secondsToWait = 1/FPS;
        else 
            secondsToWait = 0f;

        if(playOnStartup) {
            Play(true);
        }
    }

¬†What happens here is that firstly we grab the SpriteRenderer which should also be added to the GameObject which contains this script, then we just reset the frame and set the secondstoWait. If the ‚ÄėplayOnStartup‚Äô is set to true, then the animation will start playing instantly. (otherwise you can make it play from somewhere else by calling the ‚ÄėPlay‚Äô function which we‚Äôll make in a second.

 

public void Play(bool reset = false) {

        if(reset) {
            currentFrame = 0;
        }

        stopped = false;
        outputRenderer.enabled = true;

        if(frames.Length > 1) {
            Animate();
        } else if(frames.Length > 0) {
            outputRenderer.sprite = frames[0];
        }
    }

I guess most of this function also explains itself, I just reset some variables and check if there are more than 1 sprites into the array of animation sprites. If so, then start playing the animation, if not, then just set the sprite to the outputRenderer so it’s a still animation.

¬†So next up if the final part, and the ‚Äėcore‚Äô part of the Animation2D class, and can be used to add more functionality to the Animation2D class (as we have!)

public virtual void Animate() {
        CancelInvoke("Animate");
        if(currentFrame >= frames.Length) {
            if(!isLooping) {
                stopped = true;
            } else {
                currentFrame = 0;
            }
        }
    
        outputRenderer.sprite = frames[currentFrame];

        if(!stopped) {
            currentFrame++;
        }

        if(!stopped && secondsToWait > 0) {
            Invoke("Animate", secondsToWait);
        }
    }

So this function is called by ‚ÄėInvoke‚Äô and first of all Cancels any Invoke that might have been called (so that the animation doesn‚Äôt mess up by accident). Basically what it does is increment the ‚ÄėcurrentFrame‚Äô counter by 1 and then takes the sprite in the animation‚Äôs array at that index and applies it to the output.

And it checks if you want it to loop. If you want it to loop and the counter is longer or equal to the size of the animation array, then it will reset. If not, it will just stop.

And then if the animation hasn’t stopped yet it will use Invoke to re-call the Animation function.

I guess you could easily make a ‚ÄėStop‚Äô function which Cancels any Invoke of ‚ÄėAnimate‚Äô and sets ‚Äėstopped‚Äô to true.

Horse running animation in Luckslinger made with this system

That’s all for now, if you have any question or so feel free to email (duckbridge.dev[at]gmail.com) or comment. This animation class is quite simple, but we built our whole animation system based on this little class here!

I guess I could do more of these posts about more code-stuff of our game, like the loading system, saving system, some minigames, Ui stuff, some AI stuff, whatever.

My name is Marciano Viereck and I’m the programmer at Duckbridge and we’ve recently released Luckslinger on Steam. (with a 2 man team)


Related Jobs

Plarium Michigan Studio LP
Plarium Michigan Studio LP — Portage, Michigan, United States
[09.21.18]

Senior Game Developer
Spatialand
Spatialand — Venice, California, United States
[09.20.18]

Unity Lead
Spatialand
Spatialand — Venice, California, United States
[09.20.18]

UX Lead
Heart Machine
Heart Machine — Culver City, California, United States
[09.20.18]

Gameplay Engineer





Loading Comments

loader image