In this article, we will cover a Damage Animation System that will have the Enemy stop when hit and enter In Combat mode (which will be when the Enemy can attack the Player). The Enemy will remain In Combat mode until the player is a certain distance from the Enemy.
Hit Animation Setup
In the Enemy Animator, we import the Hit animation and we will want to be able to transition from Any State animation is currently in to this animation using a Trigger parameter (Hit). Once the Hit animation has played it will transition to the Idle animation.
In the Damage method of the individual Enemy script we will set this trigger.
When the Enemy is hit, it enters the Hit animation but continues to move during it. This is where we will want the Enemy to stop when hit and enter In Combat.
In Combat Mode
In the Enemy Class script, we are going to create a bool (isHit) that will track if the Enemy has took Damage.
When isHit is false, the Enemy will continue to walk towards the current waypoint.
The Enemy continues to move when hit and this is because we need to set the isHit variable true in the individual Enemy script.
Once we set the isHit true in the individual Enemy Damage method we see the Enemy will stop moving when it is hit.
After some time the Enemy will move to the Walk animation, but not exactly move. This is where we want the Enemy to remain in Idle if the Player is close or In Combat. When the Player moves a certain distance away the Enemy will resume the Walk animation and back to moving between waypoints.
Lets create a bool parameter (InCombat) and when is true will allow the transition to from Idle to Walk animation.
In the individual Enemy script we set this bool parameter true in the Damage method.
When the Enemy takes Damage it remains Idle because it is InCombat mode. Now we need to be able to detect the distance between the Enemy and Player to determine if the Enemy remains InCombat or moves back to patrolling.
Distance Between Player & Enemy
Going back to the Enemy Class script we need to get a handle on the Player using FindGameObjectWithTag. Make sure to tag the Player game object with Player.
In the Movement method, we create a local float variable that will store the distance between the Enemy’s position and the player’s position using Vector3.Distance. Once we have the distance, we will check to see if that distance is grater than 2 units and set isHit and InCombat false.
It seems the Enemy is not resuming the patrol when the Player moves out of range.
We need to be able to see what the calculated distance between the Player and Enemy to figure out what is going wrong. We can use Debug.Log and pass in the distance variable.
Looking at the Console we can see that we get several distances and none of them ever get under 2 units.
We need to get more specific and add the game objects name that the distance is being calculated for. This is simply accomplished by appending the Debug.Log with the transform name.
We see the different Enemy’s are returning different distances, which makes sense since the Enemies are in different places. But, we do notice that the distance for the Skeleton_Enemy (this is the Enemy we are currently build the script for) does go below 2 units so we know the logic is sound and there must something else prevent from working.
Looking at the Update method in the Enemy Class script, we notice when the Enemy is in the Idle animation nothing is called — not the Movement method.
Diving into the Individual Enemy script, after the Hit it moves to Idle and once it is Idle the Movement method doesn’t get called.
We add to the conditional state that will have the script do nothing if the Enemy is Idle AND the animator parameter InCombat is false. This means the script does nothing when Enemy is just Idling at the waypoint and wasn’t hit.
Now we have the Enemy entering Combat mode when hit and the Player is close but resumes patrolling when the Player moves away.
Until next time…Cheers!