Good evening, everyone! After taking a break last week, I’m back this week to continue blogging my progress in the 3D Platformer course. Admittedly, I haven’t made much further progress as work has been (again or as usual now?) quite hectic. Nevertheless, today, I will be showing how to add an enemy skeleton to the game and setting up animation and basic AI movement for it.
Once an enemy skeleton model is added to the mock level/scene, the “NavMesh Building Components” for Unity are downloaded and imported into the Unity project (note that these components are separate files that are not built into Unity but are downloaded on github and imported into Unity):
Essentially, the NavMesh components allow us to easily implement AI behaviours for an enemy object. Before working on the enemy object, however, the ground is first selected and a NavMesh is generated or baked (the light-blue shaded area represents the NavMesh or area that is “walkable”):
Next, a NavMeshAgent component is added to the skeleton object, which allows it navigate the game scene/environment using the NavMesh that was generated. The NavMeshAgent also grants a whole suite of parameters to control everything from movement or steering (i.e.- speed, acceleration, etc..) to obstacle avoidance and path finding. For now, the default parameters for the NavMeshAgent will suffice. And with that, four patrol points for the skeleton are added to the scene (which serve as destination points for the skeleton to walk to one-by-one):
In order to setup the enemy movement (as we did with creating a “PlayerController” script for the player character at the start of this blog series), an “EnemyController” script is created for the skeleton:
In the script above, the patrolPoints array is of a type “Transform” which stores the position of each element in the array, or in this case, the positions/coordinates for each of the four patrol points added to the scene. Thus, the script above produces the following result when the game is run:
Now, with the enemy animations, these are set up a bit differently than the player animations. The enemy animation will be largely “state-based” to allow for implementation of state-based AI through scripting. In other words, the coding in the script will be able to dictate what state the enemy is in: attack, idle, or running:
As you can see above for the enemy controller animator, the idle and running states are set up the same way as the player controller animator; that is, exit time is enabled and fixed duration is disabled. However, for the attack transition (from any state to attack) and attack to idle transition, exit time is disabled here while a fixed duration is assigned. This is because the attack state will eventually be dictated by the script (which I will learn and cover in the next blog). Hence, the ‘Attack’ parameter added is of a type ‘Trigger‘ instead (opposed to the float and bool parameters which were utilized before).
After setting up the skeleton animator, the enemy controller script is updated:
Essentially, what is happening in the script above is that the enemy skeleton is constantly switching back and forth between its ‘isIdle’ and ‘isPatrolling’ AI states. In the ‘isIdle’ state, the ‘Idle’ state is active (and the idle animation is played). In the ‘isPatrolling’ state, the ‘Running’ state is active (and the running animation is played):
Alrighty, it’s getting super late now and I’m glad I was able to get this blog posted in time! Next week, I will set up the skeleton’s attack animation and improve its AI – for example, chasing and attacking the player when the player is nearby. Thanks for reading and stay tuned for the next blog post!