Lesson 38 - Animations Using SpriteSheets and Animator

Tutorial Series: Introduction to Unity with C# Series

Previous Article  |  Next Article


OK I showed you earlier how to do what I call pseudo animations in code. I call it that because typically animations are a series of frames that are sort of stitched together that produce the appearance of a single changing entity. And 2D game design, this is usually accomplished with something called a SpriteSheet. What I'm going to show you now is a very simple example of how you can use spreadsheets to create this kind of animation, and to get you familiar with the process of doing this in the animation tab, as well as what's called the animator, which acts as your animation state controller. So for example transitioning from one state to another, like running or walking, and so on. But what we're going to do is a much more simplified version of this using only two transition states, and two separate spreadsheets. So the first thing I want to do is import a spreadsheet that I created that creates this appearance of our little cheesehead character opening his mouth and then he will loop a teeth chattering animation.

So in the Assets pane here let's create an Animations folder. And in that, we'll make a Cube folder so we know it's the Cube's animation. Again, it's just good to get in the habit of being organizational, that's why I'm doing this. And from here what I want to do is import the SpriteSheets into this folder, so import that. Grab that one, which is the teeth SpriteSheet one, and also grab this one and as usual, let's set the image's attributes. So it's going to be different this time, it's working with SpriteSheets so I'll show you that in a minute. First set it to point. Apply that. And so I don't forget, do it with this one as well, and we're going to want to do is click on where it says single, where it says single beside Sprite Mode and make it multiple. And then click on sprite editor here. I guess I forgot to apply some of those, so just hit apply. And here's the sprite editor where you can slice up the sheet into individual images. See right now is just one image but you want to we want to slice it up into four separate images.

So to do that, click on slice here and.. Click on grid by cell size, and it already kind of establishes the grid size. I think it detects it based on the image size. In other words evenly proportioned images within the larger sprite sheet image and just click on Slice. And there you go, it slices it up in 64x64px blocks, and hit apply to apply that as a SpriteSheet. And as you see here, the asset is correctly interpreted as now being a set of individual images by Unity. Pretty cool. So we will want this to be part of our Cube GameObject, and follow it around just the same. So let's create a GameObject for it, for the teeth animation and parent it to the Cube. So create empty, and call it Teeth like that. And we'll want to attach a sprite render, so as usual go to add component and Sprite render. And here we won't be setting the sprite sheet exactly, because we have to do it in the animation/animator, in those two parts of Unity. So we'll just leave it as is except for the sorting layer and order in layer, which we'll want to set as Player, and make sure it's above the Cube or the cheese, the little CheeseHead, so make it 1 in order in layer.

Now each GameObject can have a set of animations that belong to it. So, to add an animation, select the teeth GameObject in its hierarchy, and go to window, animation to look at the animations for this particular GameObject. Actually going to dock this, so it's a little bit easier to work with here. And here you'll see it says you can begin creating an animation. So just click create for that and you'll want to create, we'll want to create a new animation for the spreadsheet. Call it TeethOpen. It's going to save it here. Just like that. And you'll see it automatically creates an animator or an animation controller. So let's leave that for now except to rename it to TeethAnimator. You'll notice on the GameObject, an animator is also added to the GameObject by default. So right now we' ll just leave its default settings. This component will ultimately control how we transition from one animation to another but we'll worry about that little bit later. Now double click on TeethOpen, it will open up the animation tab for the TeethOpen animation clip. And now let's set the animation frames from our spreadsheet to this particular animation timeline.

So to do that, click on this little arrow beside our spreadsheet. That's now being interpreted as multiple images. I hold the shift key to make sure I click on and select each individual frame, and simply click and drag it there, and it ends up being put into this animation frame timeline, which can be seen as sort of like a movie reel, how frames play out over time whenever the animator plays this clip. So you can adjust the samples rate here to adjust the speed at which the animation plays from frame to frame. If you press the play button, you'll get a sense for how quickly this animation will play. So let's move it down just for illustrative purposes, let's move down to two samples across a frame. I guess that's how you look at it. That's how slowly a play as it loops through it. That's too slow as well, so I know ahead of time I want to make this 32 samples. So we're going to want to repeat this entire process with the other spreadsheet. And actually I can start by creating a new animation clip for the other teeth sprite sheet right here in the animation tab. Just click on here where you see TeethOpen, and we'll want to create a new clip. Call it TeethChatter right?

So now you have those two clips as part of this animation tab that's connected to your Cube. Might as well repeat this process of slicing up our spreadsheet for our second spreadsheet here. So go to there, click multiple sprite editor, slice, 64x64. It's all good. And select all this, and on the TeethChatter timeline, let's click and drag that there. Alright, after all that, we can finally now go to the animator and deal with defining our animation states, in which these animations engage and flow from one to another. So go to the animator, and double click there and it'll open up this other tab. Right here, and with the middle mouse button I'm just moving around it, clicking in the middle most button. So you notice we have a bunch of states here right. We have our TeethOpen, TeethChatter state and our entry state as well as in any state. And for so this what handles transitioning from one state to another each state has its own animation clip. You just saw how we created already two different animation clips. And actually before move forward, I think I may have forgotten to change this here. Set this to 16 samples, and back in the animator.

So we know we're going to want to go from our TeethOpen animation to our TeethChatter animation clip. So, right-click on TeethOpen, select make transition. There you go, you got this nice little transition visualized there. And actually, our normal state is going to be no animation. So we will want our entry point to go to a state that has no animation clip tied to it, so we'll need to create an empty animation state. So, right click and select Create State, empty and defaults the name 'New State,' so I'm just going to rename this normal. Now we'll want the entry to go to the normal state. So right-click and. Actually here, right click on normal, and click on set as default. Set as layer default state, right, so now our entry point now goes to our default state as being normal. And now we'll want to go from Normal to TeethOpen. Now, we'll need to define parameters for the animator that can then be set in code later on. So animator parameters let us mark exactly when and where these transitions occur, right? Which we can then reference in code, which we'll do in a moment.

So, first set the animator parameters by going to the parameters list, and we'll add a bool. And call this bool something like IsPoweredUp, so we know what this relates to, loosely relates to in code. Eventually we'll reference this in code. And since we want to engage these animations, right, starting from Normal to TeethOpen to TeethChatter. When IsPoweredUp is true, set that in the transitions dialog for both animation states. So click on this transition point from Normal to TeethOpen, and under conditions select IsPoweredUp true. There you go, just goes right there and also here as well IsPoweredUp is true. Those are the conditions in which we will make those transitions from one animation clip to another. Now to get this all hooked up in code, let's attach a new script to the Teeth GameObject and call it TeethAnimate. And open up that script, and what will need is a reference to the animator we just looked at in code. So going to start by setting a field referencing the Animator. Call this AnimatorReference, and in Start() I'll set that to GetComponent(), and pass in the Animator as the component we want to get. So this Animator, we want to get this Animator component. And will also need a reference to the PowerUpManager, which has the IsPowered bool. You need that reference.

So what we do is we need, we'll want a public GameObject to reference the. What we want to do is reference the GameObject, we'll want to grab a reference to that. And then from that GameObject, use GetComponent() to grab the instance of the PowerUpManager script. So for that let's make it a public GameObject PowerUpManagerReference. It's actually technically the PowerUpSpawn GameObject, but it has the PowerUpManager script so hopefully that's not too confusing. In Update() as I just mentioned use the GetComponent() method on this reference, this GameObject reference. So you can use GetComponent() to access Components from outside objects in exactly this way. So using the dot accessor, we get access to it's this object's GetComponent() method. And we want the PowerUpManager script, that's the component we want to retrieve, because we want the IsPowered field value whether it's true or not. We want to know that, that's all we really want the script for is just to give us that. Again, we can make it static, but I just want to do this way for illustrate purposes. And return, that's returning, just to show you, that's of course returning a PowerUpManager.

And just to show you, of course that's returning a bool, right, so make a local IsPowered, right. And now this is how we set the parameter for the Animator to whatever are powered up state is. We once again use the AnimatorReference, and it's SetBool() method to set the bool parameter. And here you have to pass in a string, right, the name of the parameter. So what was it again? IsPoweredUp. So make sure you type this in exactly. IsPoweredUp, and the second argument is going to be our actual bool that we're getting here from the PowerUpManager, which we store locally as IsPowered. And if you're wondering why I didn't put all of this just just like that in the second argument, it just looks to me a little bit more easier on the eyes doing this way. So that's only reason I did that. So save that. And of course, in the GameObject here, we're going to have a GameObject reference where we'll want to reference the PowerUpManager, the GameObject PowerUpSpawn, actually. And everything is hooked up. Let's go here, I'm going to run this in maximize state, so hopefully you can see this.

When we go into PowerUp mode, we should see the animations playing and transitioning from one to another. And can't get out of it, so that's a problem. We'll have to fix it that. Yeah, so this is an obvious problem right now that we can fix, where we should be transitioning out of the animation when going back to a normal state. So this is going to be actually pretty easy as we just need a new transition to go back to the normal state when IsPoweredUp is equal to false. So let's do this the Animator starting from if we're in TeethChatter, we can make a transition to TeethOpen, and that will happen when IsPoweredUp is false. Yep, we will transition back to the TeethOpen and we'll then transition from TeethOpen to Normal animated state when the condition is IsPoweredUp is false as well. And we should also touch up these transitions between the animation states a bit. So I messed around with this a little bit earlier. So in this transition, click on settings un-click that and then from this transition, I found. Don't have to be too precise about this I suppose, but transition duration is 0.5 and transition offset .48. And you see here you get a kind of a visual representation of how it transitions from one animation to the other. That's all I'm really doing here. You can also just do it with these handy little sliders.

So from here, from TeethChatter to TeethOpen, pretty much the same. Very similar. Maybe make it a little bit more. Scrolling in here with the middle mouse button, so I can see a little better what I'm doing there. Trying to make a little overlap. And take that off, alright, I think that's a little better, probably will have a little more smoother transition. So let's run this again to see how the little tweaks panned out. Like to see that little bit longer duration, and then get out of powered up mode and up and animation stops. Great. OK. Well, that may have seemed like kind of a lengthy process just to get a simple animation going. But if the resulting animation that I showed you here isn't all that gratifying, it's simply because of my lack of art skills. The process of creating SpriteSheets, though, is pretty much the same with any kind of spreadsheet. So if you're a good artist, or if you have a good artist, you can imagine creating print any 2D animation that you can think of using this process. And it's actually pretty easy all things considered. You know back in the day, I don't think it was this easy to make a a series of animations happen like like this with the SpriteSheet.

So obviously the process of creating SpriteSheets is beyond the scope of this less material but you can make your own spreadsheets with pretty much any 2D visual editor out there like Photoshop, Paint, Gimp and so on. They're pretty simple and intuitive once you get into it. Kind of like you know when we were kids and we'd make those little flip book animations, except you know with computers now it's all a lot easier. So if that's something you're interested in, there's a lot of information out there for you to dive into to make your own SpriteSheets. Even with limited art skills you can make things that are pretty cool. Yeah.Take it from me, this is about as good as it gets for me. Alright, so that's it for the animator for now. We'll look at solving more code issues in the next lesson.

Related Articles in this Tutorial:

Lesson 1 - Who This Course is For

Lesson 2 - What to Expect from this Course

Lesson 3 - Installation and Getting Started

Lesson 4 - Starting the First Project

Lesson 5 - Prototype Workflow

Lesson 6 - Basic Code Review

Lesson 7 - Game Loop Primer

Lesson 8 - Prototyping Continued

Lesson 9 - C# Fundamentals and Hello World

Lesson 10 - Variables and Operations

Lesson 11 - Variables and Operations Continued

Lesson 12 - Floats, Bools and Casting

Lesson 13 - If Statement Conditionals

Lesson 14 - If Statements Continued

Lesson 15 - Complex Evaluations and States

Lesson 16 - Code Syntax vs. Style

Lesson 17 - Variable Scope

Lesson 18 - Object-Oriented Programming Intro

Lesson 19 - OOP, Access Modifiers, Instantiation

Lesson 20 - Object Containment and Method Returns

Lesson 21 - "Has-A" Object Containment

Lesson 22 - "Is-A" Inheritance Containment

Lesson 23 - Static Fields and Methods

Lesson 24 - Method Inputs and Returns

Lesson 25 - Reference vs. Value Types

Lesson 26 - Introduction to Polymorphism

Lesson 27 - Navigating the Unity API

Lesson 28 - Applying What You've Learned and Refactoring

Lesson 29 - Constructors, Local Variables in the Update Method

Lesson 30 - Collecting Collectibles, Items and Powerups

Lesson 31 - Spawning and Managing Prefab Powerups

Lesson 32 - Implementing Powerup State Logic

Lesson 33 - Displaying Text, OnGUI, Method Overloading

Lesson 34 - Referencing Instantiated GameObjects, Parenting

Lesson 35 - Understanding the Lerp Method

Lesson 36 - Creating Pseudo Animations in Code

Lesson 37 - Understanding Generic Classes and Methods

Lesson 38 - Animations Using SpriteSheets and Animator

Lesson 39 - Working with Arrays and Loops

Lesson 40 - Debugging Unity Projects with Visual Studio

Lesson 41 - Camera Movement and LateUpdate

Lesson 42 - Playing Audio Clips

Lesson 43 - Routing Audio, Mixers and Effects

Lesson 44 - Adding Scoring Mechanics and Enhancements

Lesson 45 - Scene Loading and Game Over Manager

Lesson 46 - Understanding Properties

Lesson 47 - Controller Mapping and Input Manager

Lesson 48 - Understanding Enums

Lesson 49 - Dealing with Null References

Lesson 50 - Handling Variable Framerates with time.DeltaTime

Lesson 51 - Preparing the Project for Final Build

Lesson 52 - Final Build and Project Settings

Lesson 53 - Introduction to the Unity Physics Engine

Lesson 54 - Understanding FixedUpdate vs. Update

Lesson 55 - Movement Using Physics

Lesson 56 - Attack Script and Collision Events with OnCollisionEnter2D

Lesson 57 - Projectiles and Stomping Attack

Lesson 58 - Parallax Background and Scrolling Camera

Lesson 59 - Infinitely Tiling Background Sprites

Lesson 60 - OOP Enemy Classes

Lesson 61 - OOP Enemy Classes Continued

Lesson 62 - Trigger Colliders and Causing Damage

Lesson 63 - Multi-Dimensional Arrays and Procedural Platforms

Lesson 64 - Finishing Touches

Lesson 65 - Series Wrap


Please login or register to add a comment