Top down 2D game Unity

Animating Top Down 2D Games in Unity

Edward Rowe
Follow
Apr 26, 2017 · 10 min read
Im getting a little dizzy

Theres plenty of information on making side scrollers and platformers in Unity, but its 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 wed share how we are doing it.

I will explain the workflow that weve 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 its good to know the basics about Spritesheets, Animation Clips, Mechanim, and Blend Trees before reading.

Lets 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 its much harder to handle the animation because its 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 dont mirror our animations in script, because we dont 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 thats mainly what the rest of this post is about.

How we do it

Im 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 weve 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, thats ok. Ill 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 its 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 youve 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

Heres what the Idle animation looks like for our hero in Aseprite. When creating the directional animations for a state like this, its 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 artists perspective on how to do top down animations, take a look at this quick guide from Sandy Gordon [@bandygrass]:

@Bandygrasss visual tutorial for top down pixel art animation

Once you have your animations, youre 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 its 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 hasnt 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 dont use the Aseprite + Animation Improter Workflow, youll have to figure out how to create the animation clips from your spritesheet yourself, because doing it through Unitys 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 Ill 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. Thats 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. Heres 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 dont 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 dont 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 [its nonsensical]. However, blend trees also allow us to treat separate clips as variants of a single animation, and thats 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 dont 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 objects 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. Weve 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 weve set up a blend tree for each animation state, were done with the Animator Controller. Now we just need to slap it on an Animator component and were ready to go.

Are you wondering where the transitions are in our Mechanim state machine? Then Im about to blow your mind. You *dont* *need* *them*. And you dont 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 dont create a state machine that looks like this:

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

And dear god dont do this, as Ive 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 dont know.

Using the Animator

Making the character animate from here is straightforward. In the heros 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 characters 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, youd 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 thats clearly not sustainable when youve 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 Animators functionality to poll for our own events.

Closing

Thats all you should need to know to get animations up and running. To recap, heres how we set up our animation:

  • Create one Aseprite file with all animations.
  • Import the spritesheet and clips into Unity using @talecrafters 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 its 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 youd like to support us and our content, please consider buying Sparklite on any of these platforms: Steam [Mac and PC], Switch, PS4, XBox One

Sparklite for Nintendo Switch Nintendo Game Details

Sparklite is an action-adventure set in the whimsical and ever-changing land of Geodia. Battle foes in top-down action

www.nintendo.com

And if youre a starving indie, here are some other good ways to support us that wont shorten your runway:

  • Follow RedBlueGames on Twitter to keep an eye on progress and news
  • Share our posts with the community
  • Contribute code or just bug reports to any of our Open Source repositories

Video liên quan

Chủ Đề