Animating Top Down 2D Games in Unity

Edward Rowe
Red Blue Games
Published in
10 min readApr 26, 2017

--

I’m getting a little dizzy…

There’s plenty of information on making side scrollers and platformers in Unity, but it’s hard to find much about top down games such as Zelda: A Link to the Past — games where your character can face and attack in multiple directions. In Sparklite our hero can move, face, and attack in eight different directions, but thanks to our workflow and custom tools, creating new animations and updating existing ones is painless. So we thought we’d share how we are doing it.

I will explain the workflow that we’ve developed over several months and continue to improve as we move into production on Sparklite. This post is mainly intended for engineers, but it could also be useful to artists who want to know how it works under the hood. Some of our process is unique to pixel art, but not all of it.

I link to related tutorials as needed, but it’s good to know the basics about Spritesheets, Animation Clips, Mechanim, and Blend Trees before reading.

Let’s get to it.

The Challenge of Top Down Animation

In side-scrollers, characters always either face left, or right. This makes handling animation very easy, because you only have to animate one direction fully and mirror it along the Y axis in script when the character changes direction.

In “top down” games it’s much harder to handle the animation because it’s not possible to just flip or rotate the character to cover all directions. When I say “top down” I mean a slightly angled down camera view such as Diablo, or SNES RPGs such as Secret of Mana. You can see an example of how our character looks moving through all of her animations here.

There is one trick you can use to reduce the number of animations you have to make a bit, which is to mirror the Right animation to get the Left one. They make use of this in Zelda: Link to the Past, which means Link is actually not left handed, as many claim, but ambidextrous. We don’t mirror our animations in script, because we don’t want exception cases in code, but we do a lot of mirroring in the art files.

Mirrored swing animation in Zelda: Link to the Past

Creating all the art for so many animations is a feat in and of itself, so evaluate the scope of your animation requirements before doing a top down game. But creating a system to efficiently handle these animations is also a challenge, and that’s mainly what the rest of this post is about.

How we do it

I’m going to go ahead and spoil this whole article right now and show you everything we do. Advanced readers should be able to know exactly how we set up our animation from this section, and people new to top down animation will be able to see the goal for the article.

There are many workflows you can use for creating spritesheets and animation assets. Each has pros and cons, but this is what we’ve decided works best for us:

  • Each character or object has a single spritesheet (texture) file that contains every frame of every animation for that character.
  • Every animation for a character references the sprites on that single spritesheet.

Every object also has a unique animation controller that contains all of its animations as single (blend tree) states. It looks something like this:

The Animator Controller for the hero in Sparklite

Each state is made of a blend tree that looks like this:

The blend tree inside each of our hero states.

We define the facing using two parameters, FaceX and FaceY. The BlendType is 2D Freeform Catesian but we could use any of the 2D types.

If none of those pictures make sense, that’s ok. I’ll provide links to other good tutorials as I explain this workflow. The rest of this article will explain how you can replicate this workflow for your project and why it’s a good idea.

Building the Art

Before you make too much art you should find a pixel art tool that you like. I recommend using Aseprite (pronounced “ace-prite” ) for pixel art animations. Your life will be much easier if you check out my tutorial on the Aseprite Workflow Tutorial.

Once you‘ve found a tool you can begin making animations. There are two questions to answer when deciding how to build your art.

  1. What are the main actions (states) for your character? Our hero has a ton, but the obvious major ones are Idle, Moving, and Attacking.
  2. How many directions do you want your character to face? In Sparklite, the hero can face eight directions (which we call octants, or cardinals and diagonals). But you can find top down games where characters face left and right only, games where they face the cardinals, or some combination of the two. You should create an animation for every direction. We use a suffix abbreviation to denote each direction (Idle_U, Idle_UR, Idle_R, Idle_DR, Idle_D, etc.)
The Idle sequence for our hero in Aseprite

Here’s what the Idle animation looks like for our hero in Aseprite. When creating the directional animations for a state like this, it’s important that each directional animation shares the same cadence and timings. This is because the elapsed playback time should match as the character changes directions. If timings are uneven it will cause pops or unexpected movement as characters rotate through the directions. For an artist’s perspective on how to do top down animations, take a look at this quick guide from Sandy Gordon (@bandygrass):

@Bandygrass’s visual tutorial for top down pixel art animation

Once you have your animations, you’re ready to import them into Unity.

Quick side note — we store our Aseprite files in the project so they can be checked into source control. The Asperite files are the truth, not the spritesheet, so it’s important they are kept up to date and shared between users. This means we have to be careful about having multiple people editing them at the same time. But with only one artist, this hasn’t been a huge issue for us.

Import Assets to Unity

In order to get the character to animate in Unity, we need to get the sprites exported to a sliced spritesheet. We then need to make Unity Animation Clips for each animation we created in our art program (one for each direction).

At this point, if you don’t use the Aseprite + Animation Improter Workflow, you’ll have to figure out how to create the animation clips from your spritesheet yourself, because doing it through Unity’s manual workflow is honestly not an option if you plan to actually make a game. I think even giving it space in this blog post makes it seem more viable than it is, so I’ll leave it to you to look it up. But it is worth knowing how to create clips inside Unity in case you need to do it in a bind.

Generating a Spritesheet and Animation Clips from an Aseprite file using the Animation Importer tool

So with Aseprite and Animation Importer all we have to do to generate the Spritesheet and Animation clips from an Aseprite file is simply drag it into the Animation Importer. That’s it. If we change the animations in the Aseprite file, reimporting the file will update the animation without breaking references, so upkeep is minimal. If you want to use animation events or animate other properties in the animation clip, reimporting the file will change the sprite property and keep the additional properties unchanged. Here’s a closer look at the imported files:

Aseprite file, spritesheet, and idle animation clips for our Hero

Now we need to put the clips together so that the character knows how to treat them all as just a single “Idle” animation.

Putting the Animations to Work

Once we have all the clips, we need to set up an Animation Controller to use them. If you don’t know how Animation Controllers and Blend Trees work, you should study up on them before diving into this section.

We create a unique animation controller for all of our characters and objects that animate - we don’t mess with Animation Controller Overrides. In our controller, we have a blend tree for every primary animation state. Our blend trees are all the same; a set of 8 clips (one for each direction) in a 2D blend tree using two float parameters, FaceX and FaceY. Here is what that all looks like together.

Depiction of how we set up our Animation Controller

Blend trees may seem a bit weird here, since they are typically used in 3D to smoothly transition between clips. And in pixel art we would never want to be playing two clips at a time (it’s nonsensical). However, blend trees also allow us to treat separate clips as variants of a single animation, and that’s what we need here. We will just never set the blend weights to values that put the animator between two clips.

The blend tree values really don’t matter - you just have to be able to set them nicely in script. You could do a single 1D blend tree, in theory, and just count up for your directions (1-9). We use a 2D vector to represent each object’s “Face Heading”, so this works nicely for us. We just have to make sure to round face heading to the appropriate direction. If you only want to have your character face in cardinal directions you can simply leave out the diagonals in the blend tree.

You may be thinking that setting each blend tree up manually is a huge a pain, and it totally is. Any time I do a repetitive action that is subject to human error I am immediately thinking about tools to improve the workflow. We’ve created an excellent set of tools that creates all these animator controllers and blend trees when we import the Aseprite file. The tools really deserve a post of their own, which I hope to do soon, but in the meantime you can also dig through our other tools repository on GitHub to see how to build these blend trees in code.

Once we’ve set up a blend tree for each animation state, we’re done with the Animator Controller. Now we just need to slap it on an Animator component and we’re ready to go.

Are you wondering where the transitions are in our Mechanim state machine? Then I’m about to blow your mind. You *don’t* *need* *them*. And you don’t need any more parameters, either. You can simply use myAnimator.Play("StateName") to have the character immediately play that animation. Mechanim transitions are entirely unnecessary in pixel art because we always want the clips to transition in zero frames. Plus, from a clean code perspective I prefer to have all animation logic in the script, not inside mechanim. Using things like exit time (automatic transition) when a clip finishes scatters transition logic between script and mechanim and is just begging for bugs.

So please don’t create a state machine that looks like this:

Mechanim state machine with all possible transitions. This would get unwieldy pretty fast.

And dear god don’t do this, as I’ve seen people suggest on Unity Answers:

A mechanim state machine without blend trees. Are all those transitions 0 frame blends? Did I even add all transitions? I seriously don’t know.

Using the Animator

Making the character animate from here is straightforward. In the hero’s primary script, when she enters the Idle state, we use myAnimator.Play("Idle"); Every frame we evaluate the FaceX and FaceY blend parameters based on the character’s desired face heading (generally left thumbstick direction).

Caveats

There are a few things we are still researching with this workflow, but we are confident we can solve them. These are animation based root motion, and animation events.

We use animation based root motion for our character attacks and dodge, to give her interesting motion curves over the duration of the animation.

We use animation events for timed events such as playing footsteps sounds. Normally, you’d use a clip-based animation event on the frame of the clip in which the character steps down, but with 8 clips in a blend tree this is particularly cumbersome. In theory, you could manually add Unity animation events to the same frame of all clips, but that’s clearly not sustainable when you’ve got 8 clips per animation state.

Our custom tools give us the framework we need to solve these problems. The tools merit their own post, but in a nutshell we have our own asset we call an “Anim”, which contains all animation clips and a desired “blend style” (one, two, four, or eight), an optional motion curve to apply, and animation event timings. From this data we can build the corresponding Mechanim state as a blend tree, and a custom script extends Animator’s functionality to poll for our own events.

Closing

That’s all you should need to know to get animations up and running. To recap, here’s how we set up our animation:

  • Create one Aseprite file with all animations.
  • Import the spritesheet and clips into Unity using @talecrafter’s Animation Importer.
  • Add a blend tree in an animation controller for each animation state and wire up the clips.

This workflow is extremely fast, has minimal upkeep, and uses native Unity at its core so it’s robust to change. This has gone very well for us so far on Sparklite, and we doubt we will need to improve on it at all in production.

If you’d like to support us and our content, please consider buying Sparklite on any of these platforms: Steam (Mac and PC), Switch, PS4, XBox One

And if you’re a starving indie, here are some other good ways to support us that won’t shorten your runway:

--

--

Co-founder and developer at Red Blue Games. Currently working on Sparklite.