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.

46 thoughts on “A Finite State Machine in C# for Unity3D

  1. Getting the following errors:

    Assets/EnterMineAndDigForNuggets.cs(4,49): error CS0246: The type or namespace name `FSMState’ could not be found. Are you missing a using directive or an assembly reference?

    Assets/VisitBankAndDepositGold.cs(4,47): error CS0246: The type or namespace name `FSMState’ could not be found. Are you missing a using directive or an assembly reference?

  2. Yeah, it’s in FSMState.cs. It’s weird. Keep copy and pasting code into MonoDevelop but no luck. Could you post a package?

    1. I’ve uploaded an unityPackage that contains all the files required to run the example (I’ve added it to the end of the post). It works in Unity3D, which handles all imports by itself. But please note that I don’t use MonoDevelop, so it may require something else! If you find what’s happening in MonoDevelop please tell me 🙂

  3. Differences between the package and the code on this page (showing my ignorance of generics):

    Miner.cs
    private FiniteStateMachine FSM;

    EnterMineAndDigForNuggets.cs
    public sealed class EnterMineAndDigForNuggets : FSMState

    VisitBankAndDepositGold.cs
    public sealed class VisitBankAndDepositGold : FSMState

  4. Ha! Your blog ate the “” characters. Replace the # signs with “”.

    Miner.cs
    private FiniteStateMachine#Miner# FSM;

    EnterMineAndDigForNuggets.cs
    public sealed class EnterMineAndDigForNuggets : FSMState#Miner#

    VisitBankAndDepositGold.cs
    public sealed class VisitBankAndDepositGold : FSMState#Miner#

    1. Thank you! But that one uses transition tables. I prefer to embed rules for state transitions within the states themselves. At least, for now. Transition tables, however, could lead to external control of AI characters (as in an XML file), which can be quite interesting!

  5. Hi, I was trying to follow this code but I am running into a couple of problems, I was pleased to see there was a link to a project but the link appears to be broken, is it possible to get a new link to the project as I would find it useful to see how this works. Thank you.

  6. Hi, I’m trying to get my head around your code, but I’m rather new to C#. Can you perhaps give a small hint on how an “instance-based system” would look like, instead of the singleton pattern? Thanks!

    1. Hi Sebastian. Well, the instance-based system is required if different instances using the same FSM (many miners in town!) must keep their own data. Say, for example, that the EnterMineAndDigForNuggets state could only be executed three times a day (there’s a guy inside the mine that checks how many nuggets a miner digs). You could add a member variable (a counter) in the state and decrement it in the Execute function. Each miner would have its own counter.

      So, instead of using a singleton, you would create and destroy states (obviously removing the lines that define each state as a singleton). And you would change states creating a instance of the new state. Instead of

      m.ChangeState(VisitBankAndDepositGold.Instance);

      you would do something like

      m.ChangeState(new VisitBankAndDepositGold());

      Check Buckland’s free chapter, in the first link of the post. Although he uses C++ you may get the idea. I hope my silly example helped you, though!

  7. Will Awake() in FSM ever be executed? Since FSM is not inherited from MonoBehavior, and you create the FSM in Minors by calling the constructor.

  8. Thank you for sharing. I also read your post about using coroutines and I actually prefer the old school way 🙂
    Anyway I am wondering if it would make sense to use this design with coroutines to get a delay between Enter,Execute,Exit.
    Would it make sense to implement the public void ChangeState(FSMState NewState as a coroutine and then just have something like:
    yield return new WaitForSeconds(delay) before changing to Exit and Enter?

    It is just a thought, but I think I will have to find a way in the future.

  9. hm can you explain a bit further how you are gonna mix them?
    I really would appreciate this 🙂

    cheers

  10. Well, you could transform ChangeState into a coroutine, and add a yield statement like this (I’m not sure if it will work right out the box, but you get the idea)

    public IEnumerator ChangeState(FSMState NewState) {
    PreviousState = CurrentState;
    if (CurrentState != null)
    yield return new WaitForSeconds(PauseBeforeExit);
    CurrentState.Exit(Owner);
    CurrentState = NewState;
    if (CurrentState != null) {
    yield return new WaitForSeconds(PauseBeforeEnter);
    CurrentState.Enter(Owner);
    }
    }

    And you launch it in ChangeState like this:

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

    I have not tried it, but that’s the idea 🙂

  11. Yea that was exactly what I was thinking of, I just thought that you already tested something similar.
    I will give it try.
    cheers man.

  12. Nice FSM. I’ve implemented this in my current project. However, I’ve come across a situation where I need the entity to report back what state it’s in. Just thought I’d pick your brain on the best approach.

    The obvious idea is to have a set of enums, and set the entities ‘State’ property within the Enter() function, ie:

    public override void Enter(Entity entity)
    {
    entity.State = EntityState.Attack;
    }

    I can then check this property to check what state it’s in. In fact, in one state I have a ‘FinishedThis’ State set, just to report that it’s just finished the current state.

    Seems a little messy, so was wondering if you had any thoughts on a better implementation.

    1. Well, that’s more or less how I do it! Enums are static, so you can always read them. It’s not something I really like, so I try to keep things inside the same class. That is, other classes, when possible, don’t use other classes’ enums. I try to create a public function that solves the problem instead.

      For example, say you need to check if your class has ‘finishedthis’. Then you could create a public function ‘bool HasFinished()’ that returns true if the current state is FinishedThis. That way you may end up with more code… but if things change inside your class your project won’t suffer so much.

      Does it make sense? : )

  13. Yup. Sure does. 🙂

    Being a neatness freak myself, I don’t even like using the public ChangeState() for the class, outside. I prefer to have a public intermediary that does the call internally, ie.

    public void DoAttack()
    {
    fsm.ChangeState(AttackState.Instance);
    }

    An extra function call, but keeps things simple, and means I can add other functionality later if need be. 🙂

  14. Hello,

    Great Post! I was wondering if you could either explain, or provide links that explain your use of Generics here. I looked on google but was not able to find very much that can really explain it well. I’ve only been coding in Unity and have only used generics in regards to Lists and whatnot.

    Thanks for your time.

  15. Thank you, that has helped me a bit.

    Is there any disadvantage to using a state transition table like in the example that someone linked in the comment above? Why do you prefer one way over the other?

  16. Wow the whole portion of my last post containing code got deleted ._.

    Anyway I was asking if there’s a way to be able to reuse the states.. If I have an enemy class Robot that derives from my Enemy class, then in the fsm’s state classes and my Robot class, all the generics have to use (It doesn’t let me use Enemy). So I would have to have separate state classes for each different enemy. Is there a way around this while keeping the generics?

    I truly appreciate any insight you can provide >.<

  17. Could I suggest this in the public void ChangeState(FSMState NewState) method:

    if (NewState == CurrentState) {
    return;
    }

    I need it when I implement this. Thoughts?

  18. Hi,

    I had a question regarding some lines in the actual states, EnterMineAndDigForNugget and VisitBankAndDepositGold. There are two lines in each like the following:

    static EnterMineAndDigForNugget() { }
    private EnterMineAndDigForNugget() { }

    Sorry if this seems like a silly question, but I am not a super experienced programmer and would like to know what these do? I tried googling it but didn’t really know what to google.

    Thanks!

  19. Hi, found your blog as a reference in a book that I’m studying : Learning C# By developing Games By Greg Lukosek, John P. Doran, Chris Dickinson.

    Just want to thank you as your article helped me to understand the concept and use in a practical context.

    Said that I’ve noticed you mentioning a “new way” to do things in another reply, Is that coroutines? Have you wrote about it? If so can you point a link? Many thanks!

    1. Glad you found it useful! FSMs are really handy, not just for videogames! Some say they are bad practice, but we haven’t found a situation where they were an obstacle more than a solution. I guess if a game grows in complexity and you need multiple states then yes, FSMs are not enough. But usually they are handy.

      Yes, the ‘new way’ and indeed the way we usually do it is using coroutines. Have a look here!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About

This is PlayMedusa's game devlog: sketches, artwork, news, tutorials... Know more about us and our work in our MAIN SITE!

We create games mostly because we enjoy doing so. We hope you also enjoy playing them! Check them out at itchio Some can be played on the browser!

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies