

If you’ve ever built enemy AI that suddenly starts behaving strangely, switching actions randomly or getting stuck between behaviors, you’ve probably needed a clearer structure.
That structure is often a Finite State Machine, or FSM.
Finite State Machines are one of the most practical and reliable ways to build game AI. They’re simple, predictable, and easy to debug. More importantly, they scale well from small indie projects to larger games.
In this guide, we’ll break down what an FSM is, why it works so well for AI, and how to build one in Unity using clean, reusable C# code.
A Finite State Machine is a system where an object can only be in one state at a time, and it switches between states based on conditions.
Think of a basic enemy:
At any moment, the enemy is in exactly one of these states. It doesn’t patrol and attack at the same time. It transitions when certain rules are met.
For example:
That’s an FSM.
Finite State Machines are powerful because they:
When something goes wrong, you just check which state the AI is in. That alone saves hours of debugging.
A clean FSM usually has three parts:
Let’s build a simple example.
public abstract class AIState
{
protected EnemyAI enemy;
public AIState(EnemyAI enemy)
{
this.enemy = enemy;
}
public abstract void Enter();
public abstract void Update();
public abstract void Exit();
}
This ensures every state has three core methods:
public class IdleState : AIState
{
public IdleState(EnemyAI enemy) : base(enemy) { }
public override void Enter()
{
Debug.Log("Entering Idle");
}
public override void Update()
{
if (enemy.CanSeePlayer())
{
enemy.ChangeState(new ChaseState(enemy));
}
}
public override void Exit()
{
Debug.Log("Exiting Idle");
}
}
public class ChaseState : AIState
{
public ChaseState(EnemyAI enemy) : base(enemy) { }
public override void Enter()
{
Debug.Log("Starting Chase");
}
public override void Update()
{
enemy.MoveTowardsPlayer();
if (!enemy.CanSeePlayer())
{
enemy.ChangeState(new IdleState(enemy));
}
}
public override void Exit()
{
Debug.Log("Stopping Chase");
}
}
using UnityEngine;
public class EnemyAI : MonoBehaviour
{
private AIState currentState;
void Start()
{
currentState = new IdleState(this);
currentState.Enter();
}
void Update()
{
currentState.Update();
}
public void ChangeState(AIState newState)
{
currentState.Exit();
currentState = newState;
currentState.Enter();
}
public bool CanSeePlayer()
{
// Placeholder logic
return Vector3.Distance(transform.position, Vector3.zero) < 5f;
}
public void MoveTowardsPlayer()
{
transform.position = Vector3.MoveTowards(
transform.position,
Vector3.zero,
Time.deltaTime * 3f
);
}
}
Now the AI behaves clearly and predictably. Each behavior lives in its own class.
The example above creates new state objects during transitions. That works, but you can improve it by:
For larger systems, you may also introduce:
Here are typical states you’ll see in enemy AI:
You don’t need all of them. Start simple. Add complexity only when needed.
One common mistake is putting too many transition checks everywhere.
Keep transitions:
Avoid letting multiple states fight over control.
FSMs are perfect for:
They may become difficult to manage when:
In those cases, developers sometimes switch to behavior trees or utility AI. But for most games, FSMs are more than enough.
FSMs are easy to debug if you log state changes:
When AI misbehaves, ask: “What state is it in right now?” That usually leads you straight to the issue.
FSMs are lightweight. Each frame, you’re just calling one Update() method.
Performance problems usually come from:
The state machine itself is rarely the bottleneck.
Finite State Machines are simple, but that’s their strength.
They force structure. They prevent chaos. They make AI behavior readable and maintainable.
If you’re building enemy AI in Unity and things are starting to feel messy, step back and define clear states.
Idle. Patrol. Chase. Attack.
Give each one its own logic. Control transitions carefully. Keep it clean.
Most great AI systems don’t start complex. They start organized. And FSMs are one of the best ways to stay organized from the beginning.