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.

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

  1. bill December 13, 2010 / 5:14 am

    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?

    • LuisAnton December 13, 2010 / 7:43 am

      umm… It seems it can’t find the FSMState class. Did you also create that one in a file called FSMState.cs? I could upload all my files if needed.

  2. bill December 13, 2010 / 8:34 am

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

    • LuisAnton December 13, 2010 / 11:35 am

      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. bill December 14, 2010 / 6:10 am

    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. bill December 14, 2010 / 6:12 am

    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#

  5. bill December 14, 2010 / 6:15 am

    Ehhh…ok. it ate the characters again. replace the # signs with less than and greater than characters.

  6. LuisAnton December 14, 2010 / 9:47 am

    ARGH! Thank you a lot. WordPress translated angles into HTML code, and Miner wasn’t a known tag ๐Ÿ˜€

    • LuisAnton January 23, 2011 / 8:33 pm

      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!

  7. Peter Jones May 25, 2011 / 1:06 am

    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.

  8. Peter Jones May 25, 2011 / 1:29 am

    Commenting on my last post it can be ignored as I have now succeeded in downloading your project, the link is broken due to a type error in the URL:
    http://playmedusa.com/saredFiles/FSM.unitypackage
    Correcting the “sared” typo will fix this issue ^__^

  9. LuisAnton May 25, 2011 / 7:10 am

    Thank you Peter! It’s fixed now : ) Share your thoughts!

  10. Sebastian May 25, 2011 / 9:17 pm

    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!

    • LuisAnton May 25, 2011 / 9:54 pm

      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!

  11. Sebastian May 25, 2011 / 10:43 pm

    Yes, your example helps me a lot, thank you!

  12. XM June 1, 2011 / 6:50 pm

    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.

    • LuisAnton June 1, 2011 / 8:15 pm

      You are right! Awake is totally useless here.

  13. Simon June 12, 2011 / 12:20 pm

    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.

    • LuisAnton June 12, 2011 / 1:39 pm

      Well, you can certainly mix both schemes. I’m doing something similar in a current project and it is pretty useful.

  14. Simon June 12, 2011 / 2:23 pm

    hm can you explain a bit further how you are gonna mix them?
    I really would appreciate this ๐Ÿ™‚

    cheers

  15. LuisAnton June 12, 2011 / 9:38 pm

    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 ๐Ÿ™‚

  16. Simon June 13, 2011 / 1:31 pm

    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.

  17. Taz July 18, 2011 / 12:51 am

    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.

    • LuisAnton July 18, 2011 / 8:24 pm

      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? : )

  18. Taz July 18, 2011 / 10:33 pm

    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. ๐Ÿ™‚

  19. egohim September 28, 2011 / 1:23 am

    thank you. finite state machine in unity3d, it’s very useful for me.

  20. r December 28, 2011 / 9:46 am

    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.

  21. r December 29, 2011 / 2:16 am

    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?

  22. r December 29, 2011 / 3:43 am

    Sorry, I have one other question >..<

  23. r December 29, 2011 / 3:51 am

    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 >.<

  24. Andre January 6, 2013 / 6:01 pm

    Thank you! this was very helpful. No more nasty nested if / else states

  25. Nada February 1, 2013 / 7:30 pm

    Very nice post! Thank you, no need to look further now as you explained everything i need there. Great!

  26. Leonardo March 13, 2013 / 6:49 pm

    Nice, clean, easy and useful FSM implementation. Thanks for sharing! ๐Ÿ™‚

  27. Woot March 26, 2014 / 11:18 pm

    Link to download the package file is broken again…

    • LuisAnton March 28, 2014 / 9:25 am

      I’ll fix that asap ๐Ÿ˜€ Thanks!

  28. Tom Kaul May 20, 2014 / 9:20 am

    Seems broken again!

    • LuisAnton May 20, 2014 / 9:55 am

      Fixed! ๐Ÿ˜€

  29. Stewart March 26, 2016 / 8:04 pm

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

    if (NewState == CurrentState) {
    return;
    }

    I need it when I implement this. Thoughts?

    • LuisAnton June 30, 2016 / 9:28 am

      Right, indeed we usually do that in our ChangeState methods ๐Ÿ˜€

Leave a Reply

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