Unity-Notes/Tutorials/How to make a Finite State Machine (FSM).md

3.6 KiB

This is a tutorial i didn't know I needed, so here we go:

Create the State Interface

When using state interfaces, it's essentially a "Manager" it holds sub classes within, and it helps you manage the states of your characters.

Here is an example of a State Interface. When writing this code to your project, it should be outside of the main class, it will be it's own class.

public interface IState
{
    void Enter();  // Called when entering the state
    void Exit();   // Called when exiting the state
    void Update(); // Called every frame while in the state
}

What are we doing in this code sample

  1. We are defining three methods that the class will essentially automatically run, assuming it implements the IState interface.

Create the States

You can now create the "State" itself, In this case, our state will be "Idle" which means it will not have any goals it'll just be sitting there.

public class IdleState : IState
{
    public void Enter()
    {
        Debug.Log("Entering Idle State");
    }

    public void Exit()
    {
        Debug.Log("Exiting Idle State");
    }

    public void Update()
    {
        Debug.Log("Updating Idle State");
    }
}

What does this code do?

This code is doing the same as the other code snippet, but it is defined for a specific state. Each state must include three methods: Enter(), Exit(), Update().

Remember: The code is not meant to go within your main class, in fact, It could even be added to it's own script if you so pleased.

The final result

using UnityEngine;

public class EnemyAI : MonoBehaviour
{
    private StateMachine _stateMachine;
    private IdleState _idleState;
    private PatrolState _patrolState;
    private ChaseState _chaseState;

    private void Start()
    {
        _stateMachine = new StateMachine();

        // Initialize the states
        _idleState = new IdleState();
        _patrolState = new PatrolState();
        _chaseState = new ChaseState();

        // Start with the Idle state
        _stateMachine.ChangeState(_idleState);
    }

    private void Update()
    {
        // Call the State Machine's Update method
        _stateMachine.Update();

        // Example of switching between states for demonstration purposes
        if (Input.GetKeyDown(KeyCode.I))
        {
            _stateMachine.ChangeState(_idleState);
        }
        else if (Input.GetKeyDown(KeyCode.P))
        {
            _stateMachine.ChangeState(_patrolState);
        }
        else if (Input.GetKeyDown(KeyCode.C))
        {
            _stateMachine.ChangeState(_chaseState);
        }
    }
}

What does this code do?

The code does the following:

  1. Defines a StateMachine as _stateMachine; which will be handling our state transitions.
  2. Defines an IdleState, PatrolState, and ChaseState as _idleState;, _patrolState;, _chaseState; respectively, which are our classes, remember?
  3. In the start method, it
    1. Creates a new StateMachine(); on _stateMachine
    2. Creates new individual states (I like to say this is essentially "Making the state available" to the StateMachine.)
    3. Then changes the state to idle
  4. In the update method, it
    1. Runs the "Update" method on the state machine (Which means it will run the state functionality)
    2. Based on the keyboard input, it switches the state for testing purposes. You are free to change this.

Attach it to a GameObject

Now that the script is done, you can add your script to your enemy game object. Make sure it has a Nav Mesh Agent!

That's it!

Thanks for reading! Forgive me if I am wrong about some details, this is a learning exercise for me too.