The first game that comes into my mind when it comes to combos is Devil May Cry franchise. You can destroy a swarm of enemies with a single combo. The game is all about combat combos, you unlock skills that adds more moves to your combos, you breath combos, the game even rates your combos. So I thought to myself, why don’t I create one in Unity.
So, lets break down the problem, as usual, to smaller problems and tackle them one by one:
- Animations… We have to have animations that will make our combo.
- We need to create a state machine in Unity Animator so that the animations transition from one to another based on the player’s input.
- Speaking of input, we need to capture the player’s input (Mouse clicks) and as long as the player clicks the button within a certain time during the animation play, the next animation plays. If the player does not click the mouse with certain time, the character resets back to the idle state.
Sounds simple right? It is actually a pretty simple problem. Lets explore the solution step by step.
1. Getting the Animations:
I am not an animator. I know the basics on how to animate characters, but I don’t have that artistic sense on making super cool animations, especially for fighting games. The best tool you can use to get free animations is mixamo.com. You can visit that site, create an account for free and download as many animations as you like. The key thing here, is to make sure that the animations you are selecting for your combo match; which means, if the player character starts the combo by swinging a sword, then delivers a kick; you need to make sure that sword swing animation leads to the kick. Otherwise, the combo will look bad. This is very important, it is not purely technical, but a bit more of an artistic sense. The animations I picked are as follows:
You can also download the character models from mixamo.com as well and they are all rigged animations with Humanoid rigs. which is pretty cool.
I have also downloaded a Katana sword from GameDevHQ’s legendary filebase. After putting the Katana at the right place of the rig, we are ready to jump into the animations.
2. Creating the animation state machine
Unity’s animation system offers a very powerful tool to plot the way animations will work. Using Unity’s Animator you can create a state machine to link different animations together based on certain conditions. Now, lets think about how the combo will work. As you can see in figure 1, we have 5 attack animations and an idle animation. The player will always start at the idle animation which means that we will make the idle animation our default state. Then the combo, in its perfect state, will flow like this:
Idle > Attack1 >Attack2 > Attack3 > Attack4 >Attack5 >Idle
If the player keeps pressing the input buttons at the right time, the animations will play as per the diagram above, but if the player misses an input, at any attack state, the animation should then move to the idle state. This means that with every Attack state, we want to link that state with a transition to the idle state that gets played if the player does not press on the mouse button within the designated time frame. The state machine will look like this:
As you can see, each animation has a two transitions, one to the next animation and another to the idle state. But, how do we do the transition. We need some kind of a trigger that we can set to trigger the transition to any animation. Luckily, Unity allows us to create parameters that we can call from the code and create conditions based on those parameters to transition from one animation to another. The best parameter I could think of to make this work is to use trigger parameters and set them when needed. If the parameter is set, the transition to the corresponding animation will play, if not, then the animation will transition to the idle state.
Since we have five attack animations, I created five trigger parameters, each correspond to each animation; and within each transition I set the transition going to an attack animation to run if its corresponding attack trigger is set, all the transitions that are going from the attack animations to the idle animation are player on Exit Time. Here is an example of both.
As you can see in figures 4 and 5, when moving towards an attack animation the trigger parameter has to be set. If the animation finishes playing, then the animation state goes to idle.
With the animation state machine set, lets control the flow of animations through code.
3. Controlling the combo animation through code
On the player character, I created a script called ComboManager; this script handles the combo transitions and the user input. I started by creating the following variables:
The first variable is an instance of the animator so we can call in the triggers and set them to do the animation transitions. The Combo Delay variable is the maximum amount of time the player can press the input key before the combo resets to the idle state. The numClicks variable counts the number of clicks the player has pressed to determine the animation state the character should move to. The lastClickTime captures the last time the player has pressed the input key.
In the Update() function then looks like this:
I start by checking whether the time of the last input press has exceeded the threshold or not, if it did, I reset the number of clicks to zero that none of the animation events gets triggers (this will be shown later in the article)
Then I check for user input. For this demo, I use the mouse left click. If the left click is pressed we do multiple things:
- We capture the time in which that click was pressed, so we can compare it to the time threshold.
- increment the number of clicks to 1.
- Play the first attack animation but setting the trigger parameter “Attack1”. now the first attack animation is playing (Use a bit of your imagination to follow with the next part)
Finally I am just clamping the value of numClicks to be between 0 and 5 since I only have 5 animations for now.
We need then to set certain conditions to tell the animation controller to either transition to the next attack animation, or to the idle animation. Here is the problem. I want the player to press the mouse button before certain frames in the animation so they can land the next attack successfully. This means that within the animation we want to track the user input within certain key frames. How can we trigger some code when we reach to a certain key frame in Unity? The answer is, Animation Events.
Animation events allow you to enter an event in the animation dopesheet in which if the Unity at that key frame will execute a function of your choosing. Selecting where to put that animation event depends on your animations and where you want to transition to your combo attack. Simply move the animation cursor to the key frame you want and click on the Add Event button in the Animation tab. This is demonstrated in the figure below:
As you can see, I am creating an event in the first attack animation so I can check for input to move to the second attack animation. What I did I figure 8 is that I picked the right key frame where I think will blend well with the next animation and created an animation event. Then in the top right corner, I selected a function called ComboAttack1Transition(). What is that function and what does it do?
In the ComboManager() script I created the following function:
This function does only one thing, to check whether the player at that point has clicked the left click two times or greater. If the condition is true, the “Attack2” trigger is set and the animation controller will transition to the second animation If not, then the first attack animation will continue playing until it finishes and then it will move back to the idle animation automatically. This same thing is done for all the other animations. In the second attack animation I picked the right key frame that blends well with the third attack animation, set an event and call the function ComboAttack2Transition() to check for the user input. The transition functions in the ComboManager script look like this:
The reason why we do not have a fifth transition function is because when the fifth attack animation is playing, we want it to transition to the idle animation when it finishes. That’s why on the transition from the fifth attack to the idle animation, the condition is set to run on Exit Time.
With that we have a working melee combo system.