Making a Hack’n’slash #4: Importing a 3D model & animating our hero 2/2

Let’s continue working on our Mixamo character and add some animations to our hero!

This article is also available on Medium.

Last time, we started to rework our hero object to have nicer visuals: we downloaded and imported a bunch of FBX 3D models from Adobe Mixamo‘s library and we made sure to set up all the right import settings in Unity to properly extract the data from it.

But remember: these FBX models also contain animations! So, today, it’s time to make use of those animations and have our hero run around 🙂

Here’s a little demo of our animated character, just as a quick teaser:

Setting up an Animator (with a Controller)

If you take a look at the guard object you dragged into your scene in the previous episode, you’ll see that it has an Animator component on it:

This component was directly added by Unity when we asked it to auto-generate an avatar and associate it to the FBX rig. It’s what will allow us to choose an animation clip and play it on our model, by moving around the avatar bones according to the animation’s keyframes and curves.

But… wait: there is no slot to pick an animation, here. So how do we actually tell Unity which clip to play? And how can we play different clips depending on the current state of our hero?

The answer is: we need to create another asset called an Animator Controller.

This additional component is essential because it effectively determines which animation clip is currently active on the Animator, and also because it lets us choose this clip thanks to a state machine system.

The idea is that you define a set of states, one for each animation clip; then, you can create transitions between those states, either conditional or unconditional, as well as various parameters (i.e. variables that are global to the state machine) to use in said transitions.

Ok – let’s do this step by step.

Now that we have an Animator Controller, we can assign it to our Animator to actually link the two assets:

From now on, if I select the guard object in the scene, I will be able to examine the state machine of the Animator Controller linked to its Animator by opening the Animation > Animator window from the top-bar menu…

… and, at the moment, this state machine is of course empty, apart from the state-blocks that Unity auto-generates for us!

Note: you can see the name of the selected Animator Controller at the bottom of the window to check you’re working on the right asset 😉

These blocs are pretty self-explanatory and they don’t correspond to an actual animation; rather, they are specific entry points or coalesced concepts, such as the “Any State” block that represents any state in your state machine.

Don’t worry too much about those base blocks – things will be clearer when we add our own states to this state machine.

To begin with, let’s add our Idle state to the Animator Controller. To create a new state-block, just pick an animation clip asset from your project folder and drag it to the Animator window, anywhere on the grid – I’ll select my idle animation and drop it in the zone:

Because it is the first real state in the state machine, this has two consequences:

  1. a new block is created: it is named after the animation clip and automatically configured to use this animation clip
  2. the block is linked to the “Entry” point and is coloured orange: that’s because, as it is the first state, Unity sets it to be the default state, or in other words the one that the Animator will use when you start to run you game

Similarly, I can pick my run animation and drag it to the Animator window to create a second state – this time, the state is gray and it is not linked to anything:

This means that, for now, there is no way to access this state: my Animator will remain stuck in the Idle state forever but it will never get to the Run state.

To allow for this switch, we need to create a transition between the two states. This will be represented as a (directed) arrow between the two blocks, and it can be added easily by right-clicking on the source state (here: the Idle state), picking the “Make Transition” option and then left-clicking on the target state (here: the Run state).

You can do the same to create a reverse transition from the Run state back to the Idle state (so that our hero, when we release the move input, stops moving and reverts to the idle animation).

Now, obviously, we need to configure these transitions so that they implement what we want. More precisely, we want:

  • the hero to be in Idle state at the beginning of the game
  • then, if we press/activate the move input (be it via the keyboard or the gamepad controller), we want it to transition to the Run state while it starts moving
  • as long as the input is active (and the hero is moving), we want the Run state to keep playing the run animation again and again
  • finally, if we release/deactivate the move input, we want the hero to transition back to its Idle state

Ok – that’s fairly basic but it requires a bit of set up.

The first and third points are already taken care of: the Idle state is the default state, so our Animator will use it when the game starts, and we’ve set up our idle and run animations to loop so, as long as we are in the right state, it will keep on cycling through the animation forever.

The question is: how do we handle the other behaviours, namely the state transitions? How do configure these transitions so that they happen at the right time?

If you click on the Idle to Run transition arrow, you’ll see that the Inspector shows you a panel with two main parts: the timing settings and the transition conditions.

The first part allows us to set two important timing variables for our transition: the Exit Time and the Transition Time. Roughly put, the Exit Time is the amount of time to wait before actually starting the transition. The Transition Time, on the other hand, is the amount of time during which the source and the target states will be overlaid on top of each other to create a blended mix and smooth out the transition.

The second part is where we can tell Unity when this transition should occur.

There are two types of transitions in an Animator Controller: the unconditional and the conditional transitions.

An unconditional transition happens whenever a state has finished and exhausted its Exit Time. Once this threshold is reached, then the state machine will automatically trigger the transition and switch to the given target state. This is really cool if you have some animation you want to play only once, and then go back to your Idle state, for example, such as a punch attack.

A conditional transition is, naturally, a transition that only occurs when one or more specific condition(s) is (are) met. These conditions are defined using the state machine parameters; so you can check to see if a particular boolean variable is true, or if a float is more than a given value, or if a trigger has been activated.

In a nutshell, you can think of it as unconditional transitions being somewhat “automatic”, whereas conditional transitions need to have some kind of “manual triggering” – but in a very loose sense since, as we’ll discuss in the next section, this triggering can actually be done in our C# scripts! 😉

In our case, we want both transitions to be conditional because we want the first one to occur when we activate the move input, and we want the second one to happen when we deactivate it. This means that we need have some parameter we can use in our condition to trigger the transition – so let’s go to the “Parameters” tab in the top-left corner of the Animator window and create a new boolean variable:

This flag will determine whether the hero is currently running or not, so let’s just name it “Running”:

Now, we can change the settings of our transition.

First, we want the transition to occur as soon as the “Running” boolean updates its value so we need to reset the Exit Time to 0 and uncheck the “Has Exit Time” toggle. Second, we should reduce the Transition Time a bit so that the animation switch happens more quickly – I’ll put mine to 0.1.

If you look at the bottom part of the Inspector, you’ll see that because we disabled the Exit Time, the transition now absolutely requires a condition to work properly (remember that unconditional transition have nothing else but this Exit Time, so if you uncheck this property your transition has to be conditional):

We can just click on the “+” sign to add a new condition and check that our “Running” parameter is true:

For the other transition (from Run to Idle), it’s the exact same idea except that we check “Running” is false:

Checking out the result… and fixing the run animation!

The really nice thing is that we can actually test how it looks very easily, just by running the game and checking the “Running” checkbox manually! If you pin the Animator window next to your other views, you’ll even see the current state with its blue progress bar as it goes through its animation clip:

This is great… except the run animation is a bit weird: it moves the arms and the legs of our little guy alright, but it also moves the entire body! That’s definitely going to get crazy if we try to use this animation while we’re also moving the character game object…

So – how can we fix this? Well – there are two solutions.

The first one is, when you download the animation from Mixamo, to make sure that the “In Place” checkbox is on:

That will remove all this additional “global movement”, that we call the “root animation”.

But let’s say you’ve already downloaded all your animations and you can’t re-import them right now. You want to fix this asset you currently have in your Unity project. Luckily, it’s still pretty easy to do! 🙂

The first step is to locate the animation clip asset, here my Run sub-asset inside the FBX file, and duplicate it. I’ll call the new one “Run_Static” to remember this animation clip doesn’t have the root animation.

Now that it is a separated asset, I can edit this clip by opening the Animation > Animation window:

This window shows me all the keyframes this animation contains associated to the various bones in the 3D model skeleton. The one we are interested in is the first one, the updates on the position of the “Hips” bone, which is the root of the model rig.

Just right-click on the property and remove it:

Finally, we can change the animation on the Run state in our Animator Controller and pick our new Run_Static asset:

And tadaa! We’ve removed the root animation, and our guard now runs in place as expected:

Triggering animation transitions via C# script

But of course, we don’t want to toggle this “Running” checkbox manually while our game plays! We want these transitions to be triggered by our C# logic so that the animation switch happens at the same time as our overall character movement.

To do this, we just need to add a reference to our Animator component in the PlayerController class and then update the value of the “Running” parameter inside when we start or stop running.

📌 Tip: to get a slot in the Unity Inspector for a component reference, you can either make the variable public or keep it private but force it serialisation with the [SerializeField] attribute. This way, it is still handy to use but you have nice data encapsulation 🙂

First, let’s add our reference:

Of course, don’t forget to drag the component in the slot in the Inspector:

Then, let’s use this reference and update the value of the “Running” flag to true or false in our code:

To make it more efficient, here, I’m pre-computing the integer hashed equivalent of the “Running” parameter and caching it – I can store it once since it is always the same (that’s the beauty of hashes: they are deterministic and always give the same result for a given entry).

And here we are! If we run the game again and move our hero around with the input system we worked on in the previous episodes, we see that the character moves and switches between its animations accordingly!

The only issue is: he’s not rotated properly…

Fixing the rotation of our hero

In short, we need to update the forward vector of our hero so that it points in the direction of the movement. This will insure that the character is rotated properly visually.

However, we need to be careful which object we rotate exactly. If we rotate our top “Player” object, then the Cinemachine camera (which is linked to its transform) will rotate as well and we will have a completely unreadable view of the scene. If we rotate only the mesh (i.e. the deepest level in the “Player” object hierarchy), then the rotation will get continuously overwritten by the rig animations and so it will be completely useless.

What we want is to rotate the middle object, the one with the Animator component.

To do this, let’s first cache a reference to the transform of this object (based on our previous reference to the Animator component).

Then, we’ll simply update the rotation field of this transform when the hero moves so that its forward vector points in the right direction. This can be done with the Quaternion.LookRotation() method: we pass it first the forward vector to assign and then optionally the reference up vector, and the method computes the matching rotation for the object.

Because of how the FBX model is configured, I need to reverse the 3D version of my _move vector: this depends on your 3D model and you’ll have to test this out to check whether you should put the negative sign here or not 😉

Anyway – in the end, we finally get our guard hero character walking around with all its animations and the proper rotation: pretty cool, right?

Conclusion

In these last two episodes, we saw how to download and import a 3D model from Mixamo, prepare an Animator state machine and finally trigger some transitions directly from our C# scripts.

Tomorrow, we’ll have a small interlude on nice techniques for automating your imports in Unity so that you can improve your workflow even more!

2 thoughts on “Making a Hack’n’slash #4: Importing a 3D model & animating our hero 2/2”

  1. I just wanted to drop by and thank you for some well written and fun game development series. I am very glad i ended up on one of your articles on medium and found my way here. Very refreshing to read good articles instead of watching youtube videos.

    Thank you for all the work you put into this.

Leave a Reply

Your email address will not be published.