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

Extending FSM Systems Using Scriptable Objects

Utilize Scriptable Objects to define reusable state configurations that allow designers to swap NPC behaviors without modifying the underlying source code.

In this lesson, you will learn how to leverage ScriptableObjects to transform rigid, hard-coded Finite State Machines (FSMs) into flexible, data-driven systems that designers can modify without touching a single line of C#.

The Problem with Hard-Coded States

Previously, we managed state logic inside the MonoBehaviour of our NPC. If you wanted to change the speed of a "Patrol" state or swap an "Attack" state for a "Flee" state, you had to recompile your code. This tightly couples your behavior to your data, which is a common code smell that slows down iteration.

Decoupling Logic with ScriptableObjects

By moving state configuration into ScriptableObjects, we treat each state as a reusable asset. We define a base State class that contains the logic, while the ScriptableObject acts as a container for the parameters (like detection range, movement speed, or animation triggers).

Consider this pattern for a PatrolState configuration:

[CreateAssetMenu(menuName = "AI/States/Patrol")]
public class PatrolStateSO : ScriptableObject
{
    public float movementSpeed = 3.5f;
    public float waitTime = 2.0f;
    public Color gizmoColor = Color.green;
    
    // The NPC agent calls this to get its configuration
    public void Execute(NavMeshAgent agent) 
    {
        agent.speed = movementSpeed;
        // Logic for patrol goes here...
    }
}

Creating Reusable Behaviors

When your NPC’s State Machine runs, it simply references an instance of PatrolStateSO. Because it’s an asset, you can have a "SlowPatrol" and a "FastPatrol" by just creating two instances of the same ScriptableObject with different values in the Inspector.

This architectural shift allows you to swap an NPC's personality entirely. A designer can drag a "CautiousState" into the NPC's state list in the Inspector to make them behave defensively, or a "AggressiveState" to make them hunt the player, all while the game is running. You aren't changing the code; you are simply reconfiguring the data that drives the system.

Key Takeaway: By offloading state data to ScriptableObjects, you decouple your FSM logic from your game’s configuration, enabling designers to iterate on NPC behavior through the Inspector without requiring code recompilation.