Course contentsShow
← Unity Game Development
Lesson 517 of 8288. Artificial IntelligenceFree lesson

Architecting Modular State Machine Structures

Learn to design a decoupled state machine architecture using base classes to standardize state transitions and logic execution for any NPC.

In this lesson, you will learn how to design a decoupled state machine architecture that standardizes NPC behavior using base classes, ensuring your logic remains clean, reusable, and independent of specific character types.

The Problem of Monolithic States

When building AI, beginners often write massive switch or if-else blocks inside a single NPCController script. This leads to "spaghetti code" where states are tightly coupled to the character’s movement and animation logic. If you want to reuse a "Patrol" state for a different enemy, you end up copying and pasting, which creates maintenance nightmares.

The Modular Approach

To fix this, we decouple the logic by treating every state as a standalone object inheriting from a common base class. By using an abstract State class, we force every behavior to implement the same life cycle: Enter(), Execute(), and Exit().

public abstract class State 
{
    protected StateMachine machine;
    public State(StateMachine machine) => this.machine = machine;

    public virtual void Enter() { }
    public virtual void Execute() { }
    public virtual void Exit() { }
}

Standardizing Transitions

By passing a reference of the StateMachine controller into the State constructor, each state gains the power to request a transition without knowing how the character moves or animates. The StateMachine acts as the manager (the "brain"), while the State objects act as the "behaviors."

For example, a ChaseState simply monitors distance to a target. When the player is within range, it calls machine.ChangeState(new AttackState(machine)). Because the StateMachine handles the Exit() and Enter() calls, your ChaseState doesn't need to know the implementation details of the AttackState. This separation means you can mix and match states like LEGO bricks across different NPCs, such as guards, monsters, or civilians, by simply swapping out their state collections.

This modularity allows you to test individual states in isolation and prevents the controller from ever growing beyond its responsibility of managing the state life cycle.

Key Takeaway: By encapsulating NPC behaviors into independent classes derived from a common base, you create a plug-and-play state system that separates "what to do" from "how to execute it."