Simple Finite State Machine – Unity3d (C#)

UPDATE: The original state machine implementation has been radically reworked, and is now (in my opinion) one of the cleanest and most easy-to-use state machine in existence for unity. In a perfect world I’d find time to write a blog post detailing it’s benefits, but in the mean time you can get a comprehensive overview over on the project github project page. Please note that the information detailed below refers to the obsolete v1.0 of the state machine, so feel free to ignore it entirely.

Well, well – Seems it’s time again for my shining annual contribution to internet blog cruft! Do I have to post cross post this on google plus now too? Okay enough with the nonsense. The first time I encountered the State Machine design pattern, I enjoyed the concepts behind it, but I always found the actual implementation a little bit awkward and messy. I think that rather than place the blame on the pattern, this was more specifically a problem of trying to squash a square peg through a round hole. A trap that every design pattern neophyte is supposed to fall into at least once as they try to lay their shiny new patterns on top of every problem presented to them.

A while ago I was pondering the problems I encountered trying to get my very early games to “progress” through different scenarios. Scenarios such as “disable player input on Intro and show intro animations” changing to “okay, now disable animations, and enable input because the game has stared.” and then again to “Okay now disable the player input again and show the round over screen because the round is over“. What I didn’t realise at the time was that basically I was trying to manipulate state. Trying to do all of this in the same localised class led to monstrous classes hundreds of lines deep with spaghetti logic everywhere. What I didn’t know at the time was that this is a case where the State Machine pattern is perfect (also known as a FSM or Finite State Machine. I refuse to believe the references to the flying spaghetti monster (FSM) and spaghetti logic is a mere co-incidence).

Pretty much any where were you need to transition states from one state to another a FSM shines. Think a typical game scenario – Intro > Game Play > Continue > Game Play > Game Over. Each of these is a discrete state that will have it’s own rules associated with it, and ideally a path to another state. Other places where state machines also do well is managing the actions of characters. For instance the AI behaviours on an NPC character such as Patrol > Attack > Lost Target > Patrol. These are again are discrete states a FSM will help to tidy up.

Having states visible in the inspector adds a degree of flexibility

Having states visible in the inspector adds a degree of flexibility

So now that I am working on a Unity3d project once again I was in need of a State Machine implementation for C#. After looking around at various sources though, I couldn’t find anything I was really happy with. So like any design-happy-doesn’t-know-when-to-stop coder I came up with my own (inspired heavily by the one I found here). My main problems with the other implementations was that I found they were either very architecture heavy (aka designed for hardcore C# apps) or that they didn’t quite allow me to manage my states the way I wanted to.

If you’re interested in what I came up with you can find it here https://github.com/thefuntastic/Unity3d-Finite-State-Machine. It includes a very simple demo project, with examples on how to set up the state machine and the different ways you can use it to manipulate the state.

Have a peek at the github page if you want to get deeper into some of the “features” my state machine implementation offers. Feedback is more than welcome.

  • Guy

    Thanks for sharing the code, It seems very useful.
    One thing though, I had spent half an hour running the game over and over since it was ended immediately.
    At last, after remarking line 27 in StateGamePlay.cs [entity.player.ResetHealth();] , I could see all the states in action.
    Cheers!

  • Abhishek Deb

    Hi, How do I start a coroutine inside an Execute method of a particular state?

    • http://www.madewithmonsterlove.com Peter Cardwell-Gardner

      Hi There,

      Currently there is no way to do this, other than to call a method in MonoBehaviour to do it for you.

      Over the next few days though I’ll post a radical update that not only enables coroutines, but is a drastic improvement over the current implementation.

    • TheFuntastic

      Hi, up till now there was no way to do this. But I just released a brand new version of the State Machine (on the github page) that is in my opinion a much better implementation and can handle coroutines.

      (Sorry for the delayed reply, seems my previous one got lost in the ether)

  • http://www.AdamNashMusic.com Adam Nash

    Really enjoying the state machine! One question, if you have a moment – it seems that when I add any public properties to a StateMachineBehaviour, I get a Warning “Method with name get_myProperty could not resolve a matching state. Check method spelling – which is firing from the line where I initialize the state machine – stateMachine.Initialize(this) – in Awake(); The script then works totally fine, but I was wondering if you knew what this was about? Not sure why it’s trying to register those properties as states?

    • TheFuntastic

      Hi Adam,

      Glad you’re enjoying it. I added that as convenience to try and catch spelling errors. But it’s a bit dumb – essentially just checking the word before an underscore to see if it’s a valid state. Your use case is perfectly legitimate though, so I think I’ll just take the feature out.

      You can carry on using it without any negative effects. Will update as soon as I get a chance to remove the warning.

      • http://www.AdamNashMusic.com Adam Nash

        Thanks for the quick response! That’s good to know, and actually that warning has definitely helped me before with misspelled states. Dunno if this is complicating it too much, but could you hard-code an exception for get_ and set_, since they are built in to the language itself? (Until now, I didn’t even know that get/set properties were secretly calling methods named get_propertyName, etc – interesting!)

  • Suhada

    Hi Funtastic,
    I really like the simplicity of your FSM
    I’m hoping to use it in a project.

    I note that StateMachine Behaviour is based on MonoBehaviour.
    Is there any reason why it couldn’t be based on just System.Object?

    The reason I’m asking is that I’m designing a bit of code that I want to keep clear of MonoBehaviour to speed things up.
    I can see that maybe I’d need to copy your code and replace:
    public class StateMachineBehaviour : MonoBehaviour
    with
    public class StateMachineBehaviour : System.Object
    ??
    I can see that if then I DID want some FSMs to have MonBehaviour then I might end up needing two versions of the FSM code – one system and one MonoBehaviour.
    Or maybe there is a reason why you need MonoBehaviour in which case all this is moot.
    Regards
    Suhada

    • TheFuntastic

      Hi Suhada,

      It’s a monobevaviour because it needs to get a reference to StateMachineEngine which is the juice behind the whole state machine library. StateMachineEngine in turn needs to be a monobehaviour so that it can hook into various unity functions such as Update().

      It would be possible rewrite StateMachineBevhaviour to get a reference to StateMachineEngine manually, but from there I’d say you’re fighting with the design of system.

      Also, I’d question the wisdom of “keep clear of MonoBehaviour to speed things up”. Unless you’re working with millions of objects or some similarly unusual situation, I would say monobehaviours are not going to be your performance bottleneck ;)

      • Suhada

        Hi Funtatsic,
        Thanks for your reply which helped me get clearer.
        I’m writing an AI engine for an abstract strategy game. I am trying to keep the move analysis clear of MonoBehaviour because it will analyse millions of moves.
        What I’ve realised is that I mainly need your FSM to keep track of what state the game is in and this won’t be called millions of times. So I ‘ll be fine if it uses MonoBehaviour.
        Thanks again for you help.
        Suhada :-)

  • Dana Sharon

    Hey Fantastic,

    I’m trying to use your FSM (thanks by the way) and am wondering how to make it work with partial class declarations. I’d basically like to separate the states out into different source files. Am new to c# but discovered partial classes. The thing is, state methods defined in partials aren’t getting called (e.g. MyState_Enter()). any ideas? thanks!

    • TheFuntastic

      Hi there,

      To be honest I’m not familiar with partial classes at all. My first guess is that it’s tripping up the reflection strategy used to find the state methods.

      But after a quick google, it seems that partial classes don’t affect the assembly, they are just a syntax convenience. So I’m not sure.

      It’s an interesting problem, but unfortunately I don’t have very much time and this quite far away from the intended use case of the library, so regrettably I won’t be able to take a deeper look. ;)

  • http://artisanimation.com janimator0

    Hey Fantastic,

    Thanks for providing the community with this awesome FSM. quick question. How can I run a script before and after the states a run on every update. Example: I usually have a get joystick input in the beginning of every update and a update Sprite at the end.

    • TheFuntastic

      Hi There,

      The state machine is largely designed to like any other unity scripts would. So execution order issues would be solved in just the same way you would solve them in regular scripts, where you only have access to Update and Late Update. The state machine already supports both of these out the box. eg MyState_Update and MyState_LateUpdate. Of course, what if you want to execute the same code for every single state?

      You you can still use the Update and LateUpdate functions in your MonoBehaviour. If you’re having execution order issues you can solve it by manually defining your state machine to run after all other classes in the script execution order settings panel.

      If you really want a “PreUpdate” function you can easily enough hack this into the statemachine, but that will only fire per state for MyState_PreUpdate. Alternatively (and probably closest to what you are asking for) you can simply rename Update() in StateMachineBehaviour.cs to a public method and then call that from your own monobehaviour’s update function as above. This means though you will always have to remember to call this function else none of your states will work.

  • Lelex

    Hi Funtastic! Used the UnityGems state machine in the last project I worked on and am currently working with your FSM (v2.2?). I seem unable to use more than one StateMachineBehavior on the same game object without encountering an exception error.

    “Exception: No state with the name Action(the state name) can be found. Please make sure you are called the correct type the statemachine was initialized with

    MonsterLove.StateMachine.StateMachineEngine.ChangeState (System.Enum newState) (at Assets/MonsterLove/StateMachine/StateMachineEngine.cs:153)

    MonsterLove.StateMachine.StateMachineBehaviour.ChangeState (System.Enum newState) (at Assets/MonsterLove/StateMachine/StateMachineBehaviour.cs:45)

    CharacterFSM.Start () (at Assets/TBW Assets/StateMachines/CharacterFSM.cs:27)”

    This only occurs when there is more than one StateMachineBehavior component attached to the same game object. When placed on separate objects, each spawns its own State Machine Engine (as it should), and everything is otherwise functional.

    Is this a design limitation or working as intended? Isolated to me by configuration, perhaps?

    All that said, this is a really concise and straightforward FSM, and I’m super happy to use it. Many thanks.

    • TheFuntastic

      Hi Lelex,

      This is in a sense a design limitation – though not an intentional one. I didn’t anticipate users trying to add multiple state machines to the same object.

      The specific problem here is that each StateMachineBehaviour needs it’s own StateMachineEngine in order to correctly map the state transitions. So when you add the second one it overrides the first and then you see the disaster you posted above. There are good reasons why the Engine is separate from the Behaviour (such as still being able to use Awake), but in your case it causes these limitations.

      Unfortunately the only advice I can offer in this situation is a work around. Instead of applying states to the same object, nest them in child game objects. These days Unity has GetComponentInParent() so it shouldn’t be too difficult to manage in this way. ;)

      • Lelex

        Thanks so much for the response! I ended up building a tree of FSM objects to manage from a higher level and it’s working out fine. I’m mostly glad that I didn’t miss something obvious.

      • tosiabunio

        What I want to have a several components using State Machine on a single gameobject (prefab) without making it more complex hierarchy? I have many NPC models/sprites which are used for different purposes and their specific components are activated on-needed basis. At this moment only one of those components can use State Machine but I would definitely want more. Any suggestions how this can be achieved while keeping the structure flat?

        • TheFuntastic

          Hi Tosiabunio! It seems you’re relying the State Machine heavily. Thanks for all the feedback. ;)

          I’ve been giving this a bit of thought: it’s a good sign you’re wanting to use multiple instances of StateMachines. That means the pattern is working and proving itself useful! Ideally the SM should support what you want to do.

          Unfortunately it would mean a radical restructure of the way things are currently set up. Either by making a state engine live on a completely different game object or making StateBehaviour inherit directly from StateEngine. In both cases these come with significant trade offs that I’m not entirely happy with.

          To that end I’m going to say this is something I’ll have a think about. If I make any significant changes, I’d want to be absolutely sure it’s not introducing complexity for the sake of it. In the meantime though (and for the foreseeable future) I don’t see any way to use multiple state machines on the same game object and still maintain a flat structure. :/

          • tosiabunio

            I decided to follow your original suggestion and created a simple hierachy with separate object for each component and its machine. This works fine.

    • Colin Derrick Cove

      I just wanted to share my desire for this functionality. While I don’t want multiple state machines, what I do want is scripts to attach to the machine and listen for state transitions from it passively. Maybe I am in the wrong line of thinking here, but I feel this is a requirement for encapsulation of game logic.

      Example. I want a state machine to control the behavior of a basic enemy. I could have all the state management and movement inside of a single script. Now, I want to encapsulate something like the Audio logic into a different script. This script needs to listen for state changes in order to make an attack sound when it attacks, a death sound when it is dying, etc.

      How I thought this was accomplished is having a single StateMachine script, and multiple StateMachineBehavior’s that listen for states changes. But clearly, things blow up.

      Without this functionality, I cannot separate out functionality into different components correct? My one state machine class would have to contain all the code for that enemy, without the ability to share components with other enemy types that may handle states differently, or simply encapsulate functionality to keep classes cleaner.

      • TheFuntastic

        Hi Colin,

        Thanks for the interest. Based on your feedback the feedback of others, I agree that multiple state machines should be supported. I’ve created an issue to that effect: https://github.com/thefuntastic/Unity3d-Finite-State-Machine/issues/13

        However I’m pretty much on lockdown until Cadence is released later this year, so unfortunately I can’t promise any changes any time soon.

        In the meantime, if you have simple needs, say for your audio script – I have added an event to the State Engine script: Action Changed;

        Usage:

        var stateEngine = GetComponent();

        stateEngine.Changed += OnStateChanged;

        void OnStateChanged(Enum stateObj)
        {
        var state = (MyState) stateObj;

        switch(state)
        {
        case MyStates.State:
        //DoStuff;
        break;
        }
        }

        That might be able to allow you to get by in the meantime. NB the syntax highlighting is making changes, treat the above as pseudocode.

  • Tibi

    Let’s say I have 3 states: “Idle”, “Walking” and “Falling”. And a grounded flag which says if i am on the ground or not (recalculated once every FixedUpdate).

    IDLE:

    if (Input.moveX > 0.3) TransitionTo(“Walking”)

    WALKING:

    if (Input.moveX <= 0.3) TransitionTo("Idle")

    else { }

    FALLING:

    if (grounded) TransitionTo(“Idle”)

    Let’s say i am currently in “Falling” (and holding my Input.moveX > 0.3 so when I land i immediately start walking) and after a few FixedUpdates I land on something and my “grounded” flag gets set to true and the current state gets changed to “Idle”.. but I don’t immediately start walking because this is still the FixedUpdate of the “Falling” state.

    So the next FixedUpdate runs and the current state is “Idle” and Input.moveX > 0.3 so the state changes to “Walking”.. but I’m still not moving because this is the FixedUpdate of the “Idle” state.

    So only when the next FixedUpdate runs I start moving.

    But for 3 FixedUpdates I just stand there waiting for the transition conditions to process so I can get to my “Walk” state and start actually moving. I actually tried this and it has a visible glitchy effect.

    Am I missing something? Am I doing this wrong?

    • TheFuntastic

      Hi Tibi,

      Sorry for the delayed response. So the best way to reason about this is to think about it as if you were using Unity Coroutines (because essentially that’s what the State Machine uses as it’s switching mechanism). In that case yes there would be a delay of a couple of frames while state resolves itself as we can only switch to one state per an update tick (which might of course be a few fixed update calls).

      As this point I can only offer a slight workaround:
      Add a condition to your fixed update on falling that checks for if(grounded && Input.moveX > 0.3) so you can transfer directly to your walking state. That at least creates the shortest path.

      It’s on the roadmap to call state transitions without using coroutines, but last time i tried things exploded spectacularly. Even then I’m not sure that will solve the problem a 100% as fixed update is still (potentially) happening faster than update. I’ll have to give some thought and add your example to the test coverage for a future update.

      Thanks for reporting it.

  • mrthck

    How would I add OnCollisionEnter to the methods. When I do this and pass the collision as an argument I get an error ‘System.Action’ does not take 1 argument

    • TheFuntastic

      Hi! So the only way to do this currently is to modify StateEngine.cs in the following places:

      https://gist.github.com/thefuntastic/070a4c7d12ea413a45e7

      This will work pretty well, but be aware it enable OnCollisionEnter detection across all State Engine instances, which will be a performance hit if you have 1000s of objects. In future I hope to have a more modular way of enabling this.

      • mrthck

        Thanks for the help! In my case I only have a few objects so this works great.

  • Ilan Bompuis

    Hi, I’m trying to use Statemachine based on your example but when I play gameobject is automaticly deactivated… your exemple work fine but not my class… I have checked again and again I have always the same error fsm object reference is not set to an instance…

    public enum States

    {

    Init,

    Mail,

    Password,

    Success,

    Failed

    }

    private StateMachine fsm;

    public GameObject keyboardGO;

    public TextMeshProUGUI messageTxt;

    public Text InputField;

    public Text placeholderTxt;

    private string userEmail;

    private string userPassword;

    private void Awake()

    {

    //Initialize State Machine Engine

    fsm = StateMachine.Initialize(this, States.Init);

    MessageDispatcher.AddListener(“FSMACCOUNT”, ControlStates, true);

    }

    private void OnDisable()

    {

    MessageDispatcher.RemoveListener(“FSMACCOUNT”, ControlStates, true);

    }

    // Init values, first state is email

    void Init_Enter()

    {

    userEmail = “”;

    userPassword = “”;

    InputField.text = “”;

    messageTxt.text = “”;

    fsm.ChangeState(States.Mail);

    }

    private void ControlStates(IMessage rMessage)

    {

    var state = fsm.State;

    // When user press keyboard enter, control current state

    switch (state)

    {

    case States.Mail:

    RegisterEmail();

    fsm.ChangeState(States.Password);

    break;

    case States.Password:

    RegisterPassword();

    ControlUserCredential();

    break;

    }

    }

    void Mail_Enter()

    {

    messageTxt.text = “Please enter your email or phone number to login”;

    placeholderTxt.text = “EMAIL…”;

    }

    void RegisterEmail()

    {

    // TODO Control email validity

    // Register user email

    userEmail = InputField.text;

    }

    void Password_Enter()

    {

    messageTxt.text = “Please enter your password”;

    placeholderTxt.text = “PASSWORD…”;

    }

    void RegisterPassword()

    {

    // Register password

    userPassword = InputField.text;

    }

    // User are logged open …

    void Success_Enter()

    {

    keyboardGO.SetActive(false);

    // TODO…

    }

    // Wrong credential, restart FSM

    void Failed_Enter()

    {

    fsm.ChangeState(States.Init);

    }

    private void ControlUserCredential()

    {

    // TODO…

    if(userEmail == “admin” && userPassword == “admin”)

    {

    fsm.ChangeState(States.Success);

    }

    else

    {

    messageTxt.text = “Email or Password incorrect, please try again!”;

    SuperInvoke.Run(()=>fsm.ChangeState(States.Failed), 2);

    }

    }

    }

    • TheFuntastic

      Hi there, so looking at your code there doesn’t seem to be anything obviously wrong.

      One thing, You have
      StateMachine fsm = StateMachine.Initialize(this, States.Init);

      Which should be:

      StateMachine fsm = StateMachine.Initialize(this, States.Init);

      //Note the capitalization of the States enum in that you pass in. EDIT: This seems to be a disqus comment formatting thing ;)

      Otherwise, the only advice that I can give is that the StateMachine lifecycle is explicitly tied to the life cycle of the gameobject. So if you game object starts off deactivated, the Awake method won’t be called (silly Unity convention, I know, you expect Awake to always be called) and then if you receive a message from your Event bus obviously the Awake method won’t have run yet and your fsm will be null.

      • Ilan Bompuis

        Hi, Thanks for reply. Fixed code, works nice !!!

  • Dalmar Crynimar

    Hello, First of all I loved your FSM plugin, its awesome, but I need some tips.

    I have a super class and a class that derives from that super class,
    but when I am trying to make your plugin work, it don’t find the methods “x_Enter” “y_Enter”, etc, in the super class.

    private void Awake()
    {
    fsm = GetComponent().Initialize(this);
    }

    I am using this on the derived class, and the methods are protected.

    I already tried to call the Initialize on a method on superclass, but it still only find class on the derived one.

    Can you help me?
    I could use virtual methods and override them on the class, but I want to use the ones that are on super class.

    Thx!

    • TheFuntastic

      If you edit this line in the StateMachine.cs file

      var methods = component.GetType().GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic);

      And remove BindingFlags.DeclaredOnly you should get the effect you want to achieve

      • Dalmar Crynimar

        It worked <3 Thank you very much!

  • igottaaxeu

    Thanks for sharing this. I do have a question, though. I was wondering what would be the appropriate way of communicating between state machines using this. For example, when the GameState enters combat, the PlayerState should enter it’s combat state as well. I’ve set the state machines as public, but I cannot access the enum states for some reason.

    • TheFuntastic

      If you want to coordinate state machines you will have to do this in some kind of manager class.

      There are two ways you can coordinate this:

      gameSM.State will return the enum which you can query. If this isn’t working then something strange is going on.

      You can also add an event listener to be notified of state changes:

      gameSM.Changed += OnStateChanged;

      void OnStateChanged(GameStates gameState)
      {
      if(gameState == GameStates.Combat)
      {
      playerSM.ChangeState(PlayerStates.Combat);
      }
      }

      • igottaaxeu

        Thanks for the quick response. That helped.

  • knobby67

    Hi Thanks for this. One question is there a way to share a single state machine between multiple classes. So for example a master state machine can be set to Play and class_a, class_b and class_c can all have Play_Update( ) triggered by that machine?

    • TheFuntastic

      Unfortunately, there is no way to do this out to box, nor is there ever likely to be. Though there are a few ways you could approximate something close enough.

      There is both the following:

      var currentState = fsm.State;

      fsm.Changed += OnStateChanged;

      void OnStateChanged(MyStates state)
      {
      //Do Stuff
      }

      Using these two features it would be fairly easy to wire your own sharing of behaviour between classes, even if it’s not quite as elegant.

      • knobby67

        Thanks for the answer