Game Development Reference
In-Depth Information
To start, let's examine FSMs conceptually. When thinking about the enemy character,
we can observe in them a specific set of behaviors. The enemy begins the scene by
standing idle and then proceeds to wander around on patrol. During their patrol, they
might see the player character. If they do so, they'll chase the player until the player
comes into attack range. When the player enters attack range, they'll attack the player.
Now, the only exception to these rules is if the enemy sustains serious health damage
that brings them close to death. On reaching critical levels like this, the enemy will,
instead of acting aggressively, flee and search for a health-restore potion until their
health level is returned to normal.
In summarizing the enemy behavior sets like this, we've identified a number of
discrete and critical states for enemy intelligence. These are idle, patrol, chase,
attack, and flee. The enemy can be in one and only one of these states at any one
time, and each state determines how the enemy will behave. To implement this logic,
we can use an FSM design. This refers not to a specific class or object type (such
as
MonoBehaviour
or
ScriptableObject
) but rather to a design pattern, a way of
coding. An FSM begins with a finite set of states (idle, patrol, chase, and so on, as
mentioned earlier) and then manages how the states are connected to one another
logically. This determines when and how one state changes to another. The enemy
for our situation here will depend, in fact, on two-state machines under the hood:
one in C# code and the other in a Mecanim animator graph. The latter controls only
the animation that should play for the enemy mesh during each state. Let's build the
Mecanim graph first.
Right-click on the
Project
panel and create a new
Animator Controller
asset. Open
the asset inside the
Animator
window that is accessible by selecting the
Animator
option in
Window
from the application main menu, as shown here:
Accessing the animation graph