Simple FSM-like structure using Coroutines in C# (Unity3D)

The previous post got a funny comment in Reddit: “Yawn. Hang on, inheritance, singletons? Bletch”. So I thought… “I may be getting rusty… let’s give those coroutines a try”. At first, coroutines seemed like a sure way of leaving behind all my (humble) OOP practices.  I though they were some kind of goto statement, probably because I had never given them a try. Ignorance is bold.

So here’s the same Miner from our previous post (yes, the one from Programming Game AI by Examples), going back and forth from the mine to the bank. But this time, each state is implemented using a coroutine. Thanks to the yield statement, coroutines can simulate our three state stages: Enter, Execute and Exit. Even better, we may easily add pauses wherever we need. If the coroutine is used to implement an entity’s AI, it can be updated every x milliseconds (depending, for example, on the entity’s reflexes), instead of every frame.

The trick lies in the FSM coroutine:

 IEnumerator FSM() {
    // Execute the current coroutine (state)
    while (true)
	yield return StartCoroutine(state.ToString());
  }

It constantly calls and waits for the execution of the current state (which is another coroutine). If the executed state changes the current state, the next iteration will launch it properly. I guess some code should be added to change states in external events, stopping any running coroutines.

So here we go! I’ve removed some variables, but it’s mostly the same behaviour:

File: CoMiner.cs

using UnityEngine;
using System.Collections;

public class CoMiner : MonoBehaviour {
  public enum State {
    EnterMineAndDigForNuggets,
    EnterBankAndDepositGold
  }

  public State state;

  public void Awake() {
    state = State.EnterMineAndDigForNuggets;

    // Start the Finite State Machine
    StartCoroutine(FSM());
  }

  IEnumerator FSM() {
    // Execute the current coroutine (state)
    while (true)
	yield return StartCoroutine(state.ToString());
  }

  IEnumerator EnterMineAndDigForNuggets() {
    /* This part works as the Enter function
    of the previous post (it's optional) */

    print("Entering the mine...");
    yield return null;

    /* Now we enter in the Execute part of a state
    which will be usually inside a while - yield block */

    bool dig = true;
    int digged = 0;
    while (dig) {
      print("Digging... " + (digged++) + " " + Time.time);
      if (digged == 2) dig = false;
      yield return new WaitForSeconds(1);
    }

    /* And finally do something before leaving
    the state (optional too) and starting a new one */

    print ("Exiting the mine...");
    state = State.EnterBankAndDepositGold;
  }

  IEnumerator EnterBankAndDepositGold() {
    //Enter
    print ("Entering the bank...");
    yield return null;

    //Execute
    bool queing = true;
    float t = Time.time;
    while (queing) {
      print ("waiting...");
      if (Time.time - t > 5) queing = false;
      yield return new WaitForSeconds(1);
    }

    //Exit
    print ("Leaving the bank a little bit richer...");
    state = State.EnterMineAndDigForNuggets;
  }
}

This way, each class contains it’s own FSM-like structure, though a simple one. No need for multiple files for each state, which can be cumbersome if a project grows (and they always do). And its really easy to follow and understand, once you understand how coroutines work.

It is a simpler solution, but pretty useful indeed! And of course, it can be combined with good OOP practices, not exactly as shown before 🙂

A Finite State Machine in C# for Unity3D

Finite State Machines (FSMs) are pretty useful in many different contexts, as you may know if you are reading this. From a game menu to the complex behaviour of game entities, a nice FSM may improve your code’s readability and simplify its design. Or turn it into a hell of spaguetti code, depending on its implementation…

A few days ago I stumbled upon Programming Game AI by Example, by Mat Buckland, where I found a nice and comprehensive FSM explanation and an implementation in C++. It also contains a wonderful introduction to steering behaviours, path finding and a few more things, so if you are interested in game AI you should get it!

I decided to port its FSM to C# for our next project and share it. Someone may find a nice way to improve it! This version doesn’t include (yet) a messaging system, although I may add it in a near future. (Note after some critics in Reddit: if inheritance and classes bothers you, you may try using coroutines)

So, first of all, we shall define a Finite State using precisely the reason why I decided to switch from Javascript (UnityScript, ActionScript or however you call it) to C#: Generics (the other reasons being that it may be much easier finding C# programmers out there, just in case we need an extra hand, and that C# code can be easily reused in non-Unity projects). So a Finite State will be an abstract and generic class with just three methods:

File: FSMState.cs

abstract public class FSMState  <T>   {
  abstract public void Enter (T entity);
  abstract public void Execute (T entity);
  abstract public void Exit(T entity);
}

I guess it could be an interface too… I may change that in a future version. That T will point to the owner of the FSM, as you will later understand. Then we define the FSM itself, which is also a generic class:

File: FiniteStateMachine.cs

public class FiniteStateMachine <T>  {
  private T Owner;
  private FSMState<T> CurrentState;
  private FSMState<T> PreviousState;
  private FSMState<T> GlobalState;

  public void Awake() {
    CurrentState = null;
    PreviousState = null;
    GlobalState = null;
  }

  public void Configure(T owner, FSMState<T> InitialState) {
    Owner = owner;
    ChangeState(InitialState);
  }

  public void  Update() {
    if (GlobalState != null)  GlobalState.Execute(Owner);
    if (CurrentState != null) CurrentState.Execute(Owner);
  }

  public void  ChangeState(FSMState<T> NewState) {
    PreviousState = CurrentState;
    if (CurrentState != null)
      CurrentState.Exit(Owner);
      CurrentState = NewState;
      if (CurrentState != null)
        CurrentState.Enter(Owner);
  }

  public void  RevertToPreviousState() {
    if (PreviousState != null)
      ChangeState(PreviousState);
  }
};

It basically allows you to configure it (by setting its owner and the initial state), update a global and the current state (game entities are allowed to have both), change the current state and revert to the previous state when needed.

In order to use it, specific states must be defined. As they require a proper context, let’s use Mat’s West World project, simplifying it to just two states. In this West World lives a miner, whose only desire consists on accumulating gold. In our simplified version, he will work in the mine until he finds two gold nuggets. Then he will go to the bank to deposit gold in his safe box, after which he will go back to the mine. Poor guy. In the complete version he also became thirstier at each time step, and tired, after a little while working in the mine. So he could also visit the local pub and go to sleep when required. But the mine-bank iteration will be enough to show how this FSM works.

Let’s first define our miner, which contains its own Finite State Machine and a few methods that should be pretty self-explanatory, along with an enum for the possible locations:

File: Miner.cs

using UnityEngine;

public enum Locations { goldmine, bar, bank, home };

public class Miner : MonoBehaviour {

  private FiniteStateMachine FSM<Miner>;

  public Locations  Location = Locations.goldmine;
  public int           GoldCarried = 0;
  public int           MoneyInBank  = 0;
  public int           Thirst = 0;
  public int           Fatigue = 0;

  public void Awake() {
    Debug.Log("Miner awakes...");
    FSM = new FiniteStateMachine();
    FSM.Configure(this, EnterMineAndDigForNuggets.Instance);
  }

  public void ChangeState(FSMState e) {
    FSM.ChangeState(e);
  }

  public void Update() {
    Thirst++;
    FSM.Update();
  }

  public void ChangeLocation(Locations l) {
    Location = l;
  }

  public void AddToGoldCarried(int amount) {
    GoldCarried += amount;
  }

  public void AddToMoneyInBank(int amount ) {
    MoneyInBank += amount;
    GoldCarried = 0;
  }

  public bool RichEnough() {
    return false;
  }

  public bool PocketsFull() {
    bool full = GoldCarried ==  2 ? true : false;
    return full;
  }

  public bool Thirsty() {
    bool thirsty = Thirst == 10 ? true : false;
    return thirsty;
  }

  public void IncreaseFatigue() {
    Fatigue++;
  }
}

So when a miner is awakened (it can be attached to an empty GameObject, because it inherits from MonoBehaviour) it creates its own FSM with himself as its owner and an instance of the state EnterMineAndDigForNuggets.

Buckland defines each state as a Singleton pattern, but we could as well create a new state or keep instances of each state in the Miner class. We will follow Buckland’s method, but it should be easy switching to an instance-based system.

Let’s define the two required states:

File: EnterMineAndDigForNugget.cs

using UnityEngine;

public sealed class EnterMineAndDigForNuggets :  FSMState<Miner> {

  static readonly EnterMineAndDigForNuggets instance =
    new EnterMineAndDigForNuggets();
  public static EnterMineAndDigForNuggets Instance {
    get {
      return instance;
    }
  }
  static EnterMineAndDigForNuggets() { }
  private EnterMineAndDigForNuggets() { }

  public override void Enter (Miner m) {
    if (m.Location != Locations.goldmine) {
      Debug.Log("Entering the mine...");
      m.ChangeLocation(Locations.goldmine);
    }
  }

  public override void Execute (Miner m) {
    m.AddToGoldCarried(1);
    Debug.Log("Picking ap nugget and that's..." +
      m.GoldCarried);
    m.IncreaseFatigue();
    if (m.PocketsFull())
      m.ChangeState(VisitBankAndDepositGold.Instance);
  }

  public override void Exit(Miner m) {
    Debug.Log("Leaving the mine with my pockets full...");
  }
}

and

File: VisitBankAndDepositGold.cs

using UnityEngine;

public sealed class VisitBankAndDepositGold :  FSMState<Miner> {

  static readonly VisitBankAndDepositGold instance = new
    VisitBankAndDepositGold();
  public static VisitBankAndDepositGold Instance {
    get {
      return instance;
    }
  }
  static VisitBankAndDepositGold() { }
  private VisitBankAndDepositGold() { }

  public override void Enter (Miner m) {
    if (m.Location != Locations.bank) {
      Debug.Log("Entering the bank...");
      m.ChangeLocation(Locations.bank);
    }
  }

  public override void Execute (Miner m) {
    Debug.Log("Feeding The System with MY gold... " +
      m.MoneyInBank);
    m.AddToMoneyInBank(m.GoldCarried);
    m.ChangeState(EnterMineAndDigForNuggets.Instance);
  }

  public override void Exit(Miner m) {
    Debug.Log("Leaving the bank...");
  }
}

which shouldn’t be too difficult to follow. The first block in both classes is used to create the Singleton pattern in a nice thread-safe C# way. That’s what StackOverflow said, at least… Then, each state overrides three methods: Enter, which is called when the state starts; Execute, called at each time step (more about this in a moment); and Exit, called when the state ends. As they know who’s their owner (the Miner), they may make use of his public methods to alter its properties.

So when the miner Enters The Mine And Digs For Nuggets, he first changes his location in the Enter method. Then he picks a nugget and becomes more tired. If he has two nuggets, he changes his state to VisitBankAndDepositGold. When this state is executed, the miner stores all the gold he is carrying in his bank account and changes his state back to EnterMineAndDigForNuggets. Everthing comes with a nice Debug.Log message that tells what’s happening in Unity’s console.

Things could be probably improved using coroutines. And there are  many situations that will require some tweaking. One may need, for example, a pause between the Enter, Execute and Exit methods. And while it’s been said that this structure requires a lot of classes to be defined (one for each state), I like it that way. It keeps things simple and easy to debug!

Here’s a Unity Package that you may import into any Unity3D project. Simply assign Miner.cs to an empty GameObject, run the project and you should see him working and saving gold for his grandchildren in the form of incredibly boring console messages! If you highlight the GameObject you should also see his savings, tiredness and thirst increasing.