Making a RTS game #45: Importing models & animating our characters 2/2 (Unity/C#)

Let’s keep working on our RTS and see how to animate imported 3D models!

This article is also available on Medium.

In the last tutorial, we discussed how to import 3D assets into Unity that are shared in a common exchange format, .fbx, and we prepared a basic Animator to set our character’s default animation. Today, let’s continue and see how to add some smarts to our Animator, so that we can update the current animation from our C# scripts.

Note: in this tutorial, I’ll keep on using my little low-poly 3D knight character model. You can get it on CG Trader if you want! 🙂

Foreword: fixing our reference to the mesh renderer

Before we dive into animation stuff, there is a little thing we need to discuss: how to properly access our character’s mesh renderer!

For now, our code has assumed that, for all of our units, we had a child object called “Mesh” that has a renderer to toggle on or off and colour. The problem is that now that we have more complex objects, this “Mesh” object actually contains two objects: the mesh but also its armature.

So if you try and include the new character in our full game workflow, you’ll get some null references and errors when you try to create a new instance – basically, the code won’t be able to find the MeshRenderer component on the “Mesh” object… since it’s actually on a second-level child for this specific model!

To fix this, we’re going to explicitly tell the UnitManager where the mesh renderer is so that we can adapt it depending on our model and its complexity:

This obviously requires a few updates in other scripts as well, namely:

  • Building.cs:
  • CharacterManager.cs:
  • TaskFollow.cs:
  • CheckUnitInRange.cs:

Now, I can drag the right object for my Knight model, for example:

And I’ll be able to quickly set the right reference no matter the structure of my 3D model 🙂

A quick overview of the animation logic

With that said, let’s get to the real topic of today: animations!

As we said last time, Unity’s Animator relies on a state machine: each animation is in its own state, and you can define transitions to go from to another.

You basically have two types of transitions: unconditional and conditional transitions.

An unconditional transition simply waits for the animation of the current state to finish before going to the new target state. This can be pretty useful when you want to play your animation once and then “reset” to some idle or default state. Note that it obviously only works for animations that do not loop, otherwise you’ll be stuck in your current state.

A conditional transition is a bit more complex: it uses some variables or triggers (defined in your Animator) to know when it should fire. For example, you could design a basic “idle/fall” animation combo with the following logic:

  • you would add a boolean variable in your Animator called “Falling”
  • then you would drag your two animations to your Animator (as we did in the previous episode) to create your two states, Idle and Fall
  • then you would create two transitions: one from Idle to Fall, and one from all to Idle. Both are conditional: the first triggers when “Falling” is true and the second when “Falling” is false.
  • finally, in your C# code, you’d have some logic to check for the ground under your character and you would set the “Falling” parameter of the Animator accordingly

Note: don’t worry, we’ll see in just a second how to do all of this in more detail! 🙂

By cleverly manipulating variables and triggers, you can create complex behaviours – and you can even take a look at Animation Layers to blend multiple animations together…

But, in this tutorial, we’re going to focus on the basic flags and triggers, and see how to integrate this into the character behaviour tree we designed a while ago. At the moment, he’s always using his “Idle” animation, no matter the action he performs – time to have him transition and take advantage of our different animations!

Run, you fools!

Ok – first things first, let’s see how to make our character run.

Improving our Animator

We’ll use the logic I described above and first add a little variable to our character’s Animator asset: a boolean “Running” flag. This will determine whether we are in the “Idle” or the “Run” state.

To create this variable, open the Animator asset in the Animator window (remember it’s in Window > Animation > Animator) and go to the “Parameters” tab:

Then, click on the “+” sign in the top-right corner of the sidebar and choose “Bool”:

You can now name it as you want – in this tutorial, I’ll use “Running”. Be careful, we’ll use this name as reference later on, so we’ll need to match this reference exactly (casing counts!).

Note that the checkbox on the right shows you the current value of this variable. You can therefore set your starting value, if need be – for example, if you ticked this box, and after we’re done implementing the transition, then your character would immediately go to his “Run” state when the game starts.

Now, let’s actually add our “Run” state into the Animator. Like last time, drag your run animation clip to the Animator zone to immediately get a new “Run” state in the state machine. You see that it is not in orange, because it is not the default state (we set the “Idle” state as the default state).

At this point, we have two states but they are not connected! There is no way to transition to “Run”, so the character will stay in the “Idle” state forever.

To create a transition, right-click on one state, select “Make Transition” and then click on the new target state:

We’ll create two conditional transitions: one from “Idle” to “Run” and one from “Run” to “Idle”, that both check the value of our new “Running” variable.

First, let’s make the one from “Idle” to “Run”. Create the link as shown above and then select the arrow. This will show you the transition’s Inspector to customise it:

This panel reminds you which states this transition links, then it lets you define how your Animator will fade from the first animation to the second and finally it lists the conditions for this transition, if any.

Fades are really interesting because they automatically create a “blend” of your source and target animations (i.e. the animation of your current state and the animation of your new target state) and allow you to get smooth transitions between the two, instead of instantly jumping from one pose to another.

You can of course change these settings so that your animations fade more or less, and also to choose whether the transition should occur immediately or not (with the Exit Time option). In my case, for example, I want to have a short transition time (because we’re seeing the character from afar and it shouldn’t be too visible) and I want to remove the exit time entirely, because I want the transition to happen instantly when I change the value of my “Running” variable.

When you set your Exit Time to 0, you’ll notice that a warning appears at the bottom of the panel:

That’s what we discussed earlier: if your transition is unconditional, then the only “info” your Animator has is the length of the animation to play before transitioning to the next state… so if you don’t pass any condition, the Exit Time is absolutely required!

Here, however, we want to make a conditional transition. So let’s go to our conditions list and add a new one on the “Running” variable, checking that it’s true:

At this point, you can actually try this out and check that the transition does work!

Start the game while keeping the Animator window open and select the character in the scene. You’ll see that he’s currently looping on his “Idle” state (the blue bar at the bottom of the state block indicates he’s playing this animation). If you click on the “Running” checkbox on the left, you’ll see the transition arrow lights up and the character goes to the “Run” animation!

But, of course, we don’t yet have the second transition (from “Run” to “Idle”) so toggling off the “Running” variable doesn’t do anything!

We can follow the exact same process for the reverse transition: it goes from “Run” to “Idle”, it has no exit time and a condition on “Running” to check whether it is false (it has the same time settings as the first transition):

If you try to run your game again, you’ll see that you can now transition back to the “Idle” state by turning “Running” to false 🙂

Triggering transitions in our code

Of course, now, we don’t want to fire these transitions manually – we want to use our C# scripts to update the value of our “Running” variable and automatically change the character’s animation!

We’re once again going to use our UnitManager as the “brains” of the operation. It will define a new public function, SetAnimatorBoolVariable(), that first checks if there is indeed an Animator on this model, and then if it finds one it updates the given boolean variable in it:

By using this interface and checking if we do have an Animator, we make sure that the code still works even for more “simple” models: they’ll simply ignore this part of the logic altogether 😉

Now, all that’s left to do is call this function from the different nodes in our character BT when we want to transition to or from running!

  • we enable the flag in our TaskTrySetDestinationOrTarget node:
  • then, we reset it in our TaskMoveToDestination node…
  • … or if we lose our target in our CheckUnitInRange node:

And tadaa! If you run the game and create a new Soldier unit using this model, you’ll see that as soon as he’s given a destination he will transition to the “Run” state… and then go back to “Idle” when he reaches it 🙂

Adding the attack animation

Next on our to-do list is the “attack” behaviour…

Changing the idle pose

In some 3D models like my little knight, you have several idle animations depending on the context. For example, in this FBX, you have the basic “Idle” (left) and an “IdleAttack” (right) stance for when the character is getting ready to attack or take hits:

This means that we can define a new state based on this animation and some transitions from our current states, based on a new variable named “Attacking” for example:

Now, in our CheckUnitInRange script, we’ll just have to toggle this variable on or off when there is an enemy in the attack range, or when it goes away:

And our character will change his Animator state accordingly in the game:

Actually throwing some punches!

That’s all nice and good but the character is not really attacking for now. He’s just in this “attack idle” pose.

To run our attack animation, we are going to rely on another type of Animator parameter: a trigger. These are useful to call “one-shot” transitions, like the one to our “Attack” state:

I’ve called my trigger parameter “Hit”. Note that there is no checkbox next to this parameter but instead a little slot that you can click to activate the trigger and see its effect on the state machine 😉

Then, we’ll rely on an unconditional transition to automatically have the Animator return to the “IdleAttack” state once the “Attack” state is finished:

Let’s update our UnitManager to also allow for trigger parameter calls:

And finally, we’ll use it in our TaskAttack node so that every time the character hits the enemy, the animation is triggered:

If you run the game again, you’ll see that now our little knight actually runs to the target, takes an idle attack stance and then plays his attack animation once each time he throws a hit! 🙂

Going further…

This was just a quick peek at Unity’s Animator and there is plenty more we could do!

You might notice there is a slight delay between the animation and the moment the enemy loses health – you could fix this by playing around with the animations parameters, like the speed or the offset:

Also, depending on your 3D model, you might have some additional cool animations you could use… for example, my low-poly knight also has a “die” animation that we could run when the unit reaches 0 healthpoints!

Then, you could tweak the parameters of the character’s NavMesh Agent so that it turns quicker and really follows the animations and transform updates…

Conclusion

Today, we’ve looked at Unity’s animator and we’ve seen how to use variables and triggers to fire state transitions from our C# scripts. We’ve integrated it to our character behaviour tree nodes so that our character models can try and run animations… if they have an Animator on!

In the next episode, we’ll go back to some low-level systems and see how to save our game data from one play session to another…

2 thoughts on “Making a RTS game #45: Importing models & animating our characters 2/2 (Unity/C#)”

  1. Hey,

    love to see you are continuing this tutorial series!!
    And it is a great step to get something animated inside this prototype.
    As allways, keep up the good work! I’m really looking forward to what will come next. 😉

    Best wishes

Leave a Reply

Your email address will not be published.