Go to Top

This section shows how we extend the FSM framework to support SendMessage and .NET events with a coding by convention way of writing functions. Check out the finished tutorial game too...

The Game

Ok so time to look at the game.  You've been dropped on an island and need to destroy 4 buildings by calling in an F16 to bomb them.  Only problem is that you need to find the targeting computer first and the island inhabitants don't like you much.  Fortunately a supply drop has been made so you should be able to find some of the things you need!

Controls:

NOTE: Click the game window to lock the cursor.  Click escape to unlock it. If movement is jerky, right click and play full screen.

  • Arrow keys
  • Return, Mouse to fire
  • Mouse to look around
  • G to change guns
  • R to reload

The game runs off the FSM framework with many things being a state machine.  Note: enemies have multiple states, hearing and eyesight.  Stealth is best!

Unity Web Player. Install now!

For example here is the state framework for the gun:

Motivation

You should read this article if you would like to know about the core functionality of the FSM framework that this tutorial series introduces.

  • You want to learn about callable states
  • You want the lowdown on the wiring of .NET events to delegates

Before reading this it would be worth reading the Advanced Coroutines tutorial because that explains a lot of the information behind building an interruptable coroutine system that we need for our callable states.

This is an advanced, technical tutorial.  If you want to learn about using state machines then the articles for that will be produced shortly.

Tutorial Project


We are now working on StateMachineBehaviourEx from the Part2/Scene 1 folder.

Download just the state machine package here.

Callable States and Coroutines

A good state machine framework needs to have callable states.  These are states that are effectively "sub states" - they do not cause the outer state to exit, rather they run within it until such a point as they return control back to it.  The called state will execute its Enter and Exit functions, the calling state will have its Enter function suspended and resumed when the called state returns.  All other processing is directed to the called state when it is active.

To do this we hijack the coroutine system for our own interruptable coroutines.  We call the Enter states enumerator ourselves and defer processing to the real coroutine.   That enables us to swap out the IEnumerator for another one and replace it later when we want our original coroutine to start executing again.  That's all located in a class called InterruptableCoroutine which we create an instance of for the enter and exit routines.

	/// <summary>
	/// A coroutine executor that can be interrupted
	/// </summary>
	public class InterruptableCoroutine
	{
		IEnumerator enumerator;
		MonoBehaviour _behaviour;

		/// <summary>
		/// Coroutine info for running YieldInstructions as a separate coroutine
		/// </summary>
		private class CoroutineInfo
		{
			/// <summary>
			/// The instruction to execute
			/// </summary>
			public YieldInstruction instruction;
			/// <summary>
			/// Whether the coroutine is complete
			/// </summary>
			public bool done;
		}

		/// <summary>
		/// A coroutine that runs a single yield instruction
		/// </summary>
		/// <returns>
		/// The instruction coroutine.
		/// </returns>
		/// <param name='info'>
		/// The info packet for the coroutine to run
		/// </param>
		IEnumerator YieldInstructionCoroutine(CoroutineInfo info)
		{
			info.done = false;
			yield return info.instruction;
			info.done = true;
		}

		/// <summary>
		/// Waits for a yield instruction
		/// </summary>
		/// <returns>
		/// The coroutine to execute
		/// </returns>
		/// <param name='instruction'>
		/// The instruction to run
		/// </param>
		IEnumerator WaitForCoroutine(YieldInstruction instruction)
		{
			var ci = new CoroutineInfo {instruction = instruction, done = false };
			_behaviour.StartCoroutine(YieldInstructionCoroutine(ci));
			while(!ci.done)
				yield return null;
		}

		IEnumerator Run()
		{
			//Loop forever
			while(true)
			{
				//Check if we have a current coroutine
				if(enumerator != null)
				{
					//Make a copy of the enumerator in case it changes
					var enm = enumerator;
					//Execute the next step of the coroutine
					var valid = enumerator.MoveNext();
					//See if the enumerator has changed
					if(enm == enumerator)
					{
						//If this is the same enumerator
						if(enumerator != null)
						{
							//Get the result of the yield
							var result = enumerator.Current;
							//Check if it is a coroutine
							if(result is IEnumerator)
							{
								//Push the current coroutine and execute the new one
								_stack.Push(enumerator);
								enumerator = result as IEnumerator;
								yield return null;
							}
							//Check if it is a yield instruction
							else if(result is YieldInstruction)
							{
								//To be able to interrupt yield instructions
								//we need to run them as a separate coroutine
								//and wait for them
								_stack.Push(enumerator);
								//Create the coroutine to wait for the yieldinstruction
								enumerator = WaitForCoroutine(result as YieldInstruction);
								yield return null;
							}
							else
							{
								//Otherwise return the value
								yield return enumerator.Current;
							}
						}
						else
						{
							//If the enumerator was set to null then we
							//need to mark this as invalid
							valid = false;
							yield return null;
						}
						//Check if we are in a valid state
						if(!valid)
						{
							//If not then see if there are any stacked coroutines
							if(_stack.Count >= 1)
							{
								//Get the stacked coroutine back
								enumerator = _stack.Pop();
							}
							else
							{
								//Ensure we don't use this enumerator again
								enumerator = null;
							}
						}
					}
					else
					{
						//If the enumerator changed then just yield
						yield return null;
					}
				}
				else
				{
					//If the enumerator was null then just yield
					yield return null;
				}
			}
		}

		/// <summary>
		/// Initializes a new instance of the <see cref="StateMachineBehaviour.InterruptableCoroutine"/> class.
		/// </summary>
		/// <param name='behaviour'>
		/// The behaviour on which the coroutines should run
		/// </param>
		public InterruptableCoroutine(MonoBehaviour behaviour)
		{
			_behaviour = behaviour;
			_behaviour.StartCoroutine(Run());
		}

		/// <summary>
		/// Stack of executing coroutines
		/// </summary>
		Stack<IEnumerator> _stack = new Stack<IEnumerator>();

		/// <summary>
		/// Call the specified coroutine
		/// </summary>
		/// <param name='enm'>
		/// The coroutine to call
		/// </param>
		public void Call(IEnumerator enm)
		{
			_stack.Push(enumerator);
			enumerator = enm;
		}

		/// <summary>
		/// Run the specified coroutine with an optional stack
		/// </summary>
		/// <param name='enm'>
		/// The coroutine to run
		/// </param>
		/// <param name='stack'>
		/// The stack that should be used for this coroutine
		/// </param>
		public void Run(IEnumerator enm, Stack<IEnumerator> stack = null)
		{
			enumerator = enm;
			if(stack != null)
			{
				_stack = stack;
			}
			else
			{
				_stack.Clear();
			}

		}

		/// <summary>
		/// Creates a new stack for executing coroutines
		/// </summary>
		/// <returns>
		/// The stack.
		/// </returns>
		public Stack<IEnumerator> CreateStack()
		{
			var current = _stack;
			_stack = new Stack<IEnumerator>();
			return current;
		}

		/// <summary>
		/// Cancel the current coroutine
		/// </summary>
		public void Cancel()
		{
			enumerator = null;
			_stack.Clear();
		}

	}

There's one further requirement - we need to be able to pause the execution even when we are executing a YieldInstruction for the real enumerator - that's so we can suspend execution even if we were in the middle of a WaitForSeconds - to do that we have a function called WaitForCoroutine that takes the yield instruction and just creates a wrapper that waits for the single YieldInstruction to complete

We wrap all of the delegates for our state in a class called State - this enables us to push them enmasse onto a stack when we call a new state and retrieve them again later.

So when we call a state:

  • Suspend the current Enter coroutine
  • Push the current delegates onto the stack
  • Create a new state and populate it with the new state
When that state Returns:
  • Call it's Exit function (start its enumerator)
  • Pop the delegates off the stack
  • Resume the original state's Enter coroutine

Cleaning Up

To clean up the system we also make it possible to define the Enter and Exit states as void in the code if they don't need to be coroutines - in that case we wrap them in a dummy coroutine and call that again.

States On Other Objects

It sometimes makes a lot of sense to have states implemented on other objects control a different object.  Back in part #2 you may have noticed that we cached the transform, animation etc of the current gameObject - this makes a lot of sense for performance reasons but also allows us to have the actually be the values from a different object.  This gives us great flexibility.  Calling Represent on a state machine behaviour makes all of its local variables represent some other object.

We can set a state to be a different state machine behaviour call calling SetState - passing a state value and also the this of the behaviour we want to use to control it.  This can be seen in the tutorial project where the main camera is controlled by a camera position and angle component (CameraLook2 attached to an object with a LookPosition) - this makes the camera move to the look position during execution.

Due to this overriding of the traditional values of gameObject, transform, GetComponent etc means that we still probably want to get a reference to the object on which the script is actually attached (the CameraLook2 uses this to move the camera to its position and rotation).  So we enable you to get that from localTransform and localGameObject and also provide GetLocalComponent etcetera.

Messages

So far we have a state machine framework that can handle some well known methods that can be implemented on a script (Update, OnCollisionEnter etc).  What about those messages that we send ourselves using SendMessage?

The answer to that is we may in some cases need to delegate those to a state too.  We do that using a combination of reflection and system diagnostics!

void SomeMessageYouSend(int parameter)
{
     SendStateMessage(int parameter);
}

This is how we can define a custom message handler that will delegate to states - the states then implement STATENAME_SomeMessageYouSend(int parameter) and it calls them automatically.

The interesting thing is how we actually send that message.

    protected void SendStateMessage(params object[] param)
	{
		var message = currentState.ToString() + "_" + (new StackFrame(1)).GetMethod().Name;
		SendMessageEx(message, param);
	}

So we use the System.Diagnostics namespace to get the name of the message being called (note how we didn't need to pass that?) Then we use a variable parameter list which can take any number of parameters and we call on to our SendMessageEx function.

We could just use a SendMessage here - but they are very slow and we can optimise the solution if the message is called frequently and especially if it is actually an Action like void SOMEMETHOD().

	void SendMessageEx(string message, object[] param)
	{
		//Have we found that a delegate was already created
		var actionSpecified = false;
		//Try to get an Action delegate for the message
		Action a = null;
		//Are we passing no parameters
		if(param.Length == 0)
		{
			//Try to uncache a delegate
			if(_actions.TryGetValue(message, out a))
			{
				//If we got one then call it
				actionSpecified = true;
				//a will be null if we previously tried to get
				//an action and failed
				if(a!=null)
				{
					a();
					return;
				}
			}
		}

		//Otherwise try to get the method for the name
		MethodInfo d = null;
		Dictionary<string, MethodInfo> lookup = null;
		//See if we have scanned this type already
		if(!_messages.TryGetValue(GetType(), out lookup))
		{
			//If we haven't then create a lookup for it, this will 
			//cache message names to their method info
			lookup = new Dictionary<string, MethodInfo>();
			_messages[GetType()] = lookup;
		}
		//See if we have already search for this message for this type (not instance)
		if(!lookup.TryGetValue(message, out d))
		{
			//If we haven't then try to find it
			d=GetType().GetMethod(message, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			//Cache for later
			lookup[message] = d;
		}
		//If this message exists		
		if(d != null)
		{
			//If we haven't already tried to create
			//an action and there are no parameters
			if(!actionSpecified && param.Length==0)
			{
				//Ensure that the message requires no parameters
				//and returns nothing
				if(d.GetParameters().Length == 0 && d.ReturnType == typeof(void))
				{
					//Create an action delegate for it
					var action = (Action)Delegate.CreateDelegate(typeof(Action),this,d);
					//Cache the delegate
					_actions[message] = action;
					//Call the function
					action();
				}
				else
				{
					//Otherwise flag that we cannot call this method
					_actions[message]= null;
				}
			}
			else
				//Otherwise slow invoke the method passing the 
				//parameters
				d.Invoke(this, param);

		}

	}

We do a lot of caching in this routine that means it never checks the same type twice for the same message - and the optimisation of calling actions as direct delegates makes these very fast.  It could be extended to have special caches for methods that take a specified set of values - perhaps a float one would be useful to cache damage messages - but I didn't feel it was necessary here.

.NET Events

We can also massively benefit from wiring up .NET events to our states.  These will be very fast to execute, but bear in mind events are wired at a point in time (usually on state change or on an explicit call to RefreshEvents) so dynamically instantiated objects can have their events missed unless care is taken.  An event subscription model that alleviates this restriction and runs much faster than SendMessage will be the subject of a subsequent tutorial.

We have WireEvents and UnwireEvents which are called as part of the state change process there let us write event handlers for .net events like this:

void SOMESTATE_OnEVENTNAME_SELECTOR(int x)
{
}

void Waiting_OnClicked_BigButton()
{
}

The way it works is that the SELECTOR element is a way of finding objects - by default 3 selector types are provided out of the box:

  • _NAME - where the name is the name of a game object.  All scripts attached to the object will be searched for an event called EVENTNAME and any local methods called SOMESTATE_OnEVENTNAME with a compatible signature will be wired to them
  • _Child_NAME_NAME_NAME -  the NAME is then the path to the name of the child where normal path / are replaced with _.  For example Waiting_OnClicked_Child_Status_BigButton - would find the child at the path from the current object /Status/BigButton
  • _Tag_TAGNAME - all game objects with the TAGNAME that contain scripts with an event called EVENTNAME will be wired to a local method called SOMESTATE_OnEVENTNAME if the signatures are compatible.
You can write your own way of finding objects that might contain the events too: 
By overriding OnWireEvents(EventDef eventInfo) you can access the selector and the event name and return an array of objects that should be considered for wiring.  For example you could have just an array of GameObjects that you returned always - those that you had set in the Inspector perhaps - or you could process the SELECTOR yourself using any format you like.  This makes it pretty flexible.

Summary

In this section we have seen the clean up from our first delegate driven state machine framework to a fully functioning, high performance system that can call states, delegate them to other objects and wire .NET events.

Next up - how to really use it to make a game!

, , , ,

51 Responses to "Finite State Machines #3 – Final State Machine Framework"

  • Titan
    December 2, 2012 - 2:47 pm Reply

    Hi,
    got some problem with this article :)
    - in the graph showing the state machine of the gun, the reload function have a “no bullet” transition that lead into a machineGunHit state where it apply damage => ?
    - the full package with the game bug on my unity 3.5.6, when the game start, some exception are thrown about the gun (sorry can’t be more precise, i deleted the package :( ), we still can move around but not shoot or switch weapon.
    -on the web player version, it’s working great (except that i dont understand what to do^^), but the gun bug (again :p) if a cut scene start -about an house and a F16- while you are shooting, must be a state machine fail imo.

  • blazeq
    December 3, 2012 - 8:24 am Reply

    Thank you for this good approach.
    I really wanted that a method call works differently for each state.

    I’m using Unity3D for 7 months and not familiar with C# reflection yet.
    This source code is very helpful to me.

    I’ll use this StateMachineBehaviour in my game.
    But I want to know if there are updates or bug fixes after posting.

    If you have some test codes to prove each operation of this code, it will be very helpful to me.

    • whydoidoit
      December 3, 2012 - 8:36 am Reply

      Sorry both, it appears that something has gone wrong with my upload then!

      I will check it out and upload a fixed version.

      @Titan – looks like I missed a state transition there with the gun/f16 behaviour – will check it out and post later.

      It’s a big file, may take sometime to update, will post again when it is done.

      • blazeq
        December 4, 2012 - 2:48 am Reply

        Thanks. :)
        I’m trying to fully understand the StateMachineBehiourEx.cs.
        I am very cautious about using this code in my game without fully understanding it
        because it replaces many default configurations of MonoBehaviour.

        In the source code of InterruptableCoroutine,
        I think the ‘else’ block from line 102~108 is unreachable. Could you confirm it?

      • blazeq
        December 4, 2012 - 4:28 am Reply

        And in line 76 of InterruptableCoroutine code,
        if enumerator.MoveNext() returned false, enumerator.Current throws an exception.
        So I think it’s better to reassign _enumerator if MoveNext() returns false.

        if (!_enumerator.MoveNext())
        {
        _enumerator = (_stack.Count >= 1) ? _stack.Pop() : null;
        }

  • whydoidoit
    December 4, 2012 - 9:36 am Reply

    Ok, sorry about the confusion – it appears that I somehow managed to overwrite the proper version of StateMachineBehaviourEx while trying to make up the package.

    So there was a problem with state switching and calls because the configuration for a standard state was not caching the enumerator and hence it wasn’t correctly re-entering the state.

    @blazeq – unreachable code is a warning in Unity – I see no such warnings but have played around with the code now so your line numbers aren’t quite right for me any more – can you elaborate and I will attempt to explain?

    I have modified the code to check for a valid return before testing Current, though I have never seen that throw an error – you are right that it might.

    • blazeq
      December 5, 2012 - 3:06 am Reply

      Thank you for your kind and fast reply.

      I used the line number of the above code block in this post.
      I also cannot any warning about the unreachable code but I think that null check was not necessary any more in the nested case sentences.

      if(enumerator != null)
      {
      //Make a copy of the enumerator in case it changes
      var enm = enumerator;
      //Execute the next step of the coroutine
      var valid = enumerator.MoveNext();
      //See if the enumerator has changed
      if(enm == enumerator)
      {
      // [blazeq] enumerator cannot be null here.
      because enum is not null and enumerator equals to enm.
      // [blazeq] so, null check is not necessary here.
      //If this is the same enumerator
      if(enumerator != null && valid)
      {
      //Get the result of the yield
      var result = enumerator.Current;

      Deep if-else sentences with yield commands are too complex to me. :)
      So, I rewrite Run() method like below.

      IEnumerator Run()
      {
      while (true)
      {
      if (_enumerator == null)
      {
      yield return null;
      }
      else
      {
      var prevEnumerator = _enumerator;

      if (!_enumerator.MoveNext())
      {
      _enumerator = (_stack.Count >= 1) ? _stack.Pop() : null;
      continue;
      }

      if (_enumerator != prevEnumerator)
      {
      yield return null;
      }
      else
      {
      var result = _enumerator.Current;
      if (result is IEnumerator)
      {
      _stack.Push(_enumerator);
      _enumerator = result as IEnumerator;
      yield return null;
      }
      else if (result is YieldInstruction)
      {
      _stack.Push(_enumerator);
      _enumerator = WaitForCoroutine(result as YieldInstruction);
      yield return null;
      }
      else
      {
      yield return _enumerator.Current;
      }
      }
      }
      }
      }

  • whydoidoit
    December 4, 2012 - 9:42 am Reply

    Both packages are updated – hopefully right now!

  • whydoidoit
    December 5, 2012 - 5:17 am Reply

    Yes that looks ok to me :)

  • Scott
    December 12, 2012 - 9:08 pm Reply

    Mike,

    I am not seeing any implementation of STATE_Update() {} anywhere in the FSM?

    I see your attempted use with regard to the “bezerk” state, but I am unsure if it is actually being run.

    Eagerly awaiting Part IV.

    • whydoidoit
      December 12, 2012 - 9:12 pm Reply

      So the F16 uses a lot of XXXX_Update calls for positioning and the guns use them for input detection and switching to firing modes.

      Yep, so many things to write :) That and a day job :(

      • Scott
        December 12, 2012 - 10:07 pm Reply

        Ah, I figured out my problem. I was overriding the FSM Update… Am I misusing the system if I need to have an update on my behaviour script which is called every frame?

  • whydoidoit
    December 12, 2012 - 11:01 pm Reply

    A general Update which is irrespective of what state the FSM is in? I don’t think I implemented an “All_Update” which I have done in the past.

    You can write an Update() function, but if you want it to also defer you would need to call state.DoUpdate() from within it.

  • Terry Morgan
    January 7, 2013 - 7:53 pm Reply

    quote
    how to really use it to make a game!
    unquote

    Nice, if you could make it so I could just assign the fsm’s to different monsters, possibly
    a ranged weapon monster like the Unity FPS tutorial robots.

    I got the laptop but don’t know how to ‘paint the target’

  • Gazi Alankus
    January 15, 2013 - 8:48 pm Reply

    Great code! I’m testing the framework and I’m sure I’m going to love coding this way.

    One thing made me curious: it seems like making the exit state function be a coroutine works, and it is allowed to execute until the newly set state is exited (even though the coroutine belongs to the previous state).

    To give an example, here are the functions that are being called

    currentState = A;
    A_EnterState() is called
    currentState = B;
    B_EnterState() is called
    A_ExitState() is called (this one does something periodically with yields()
    // A_ExitState()’s periodic code keeps running
    currentState = A;
    A_EnterState() is called
    B_ExitState() is called
    //A_ExitState()’s periodic code no longer is running

    While this is nice because it’s good to know that ExitState won’t run forever by accident, it’s a little counterintuitive. Perhaps it would make more sense to stop A_ExitState() from running again after A_ExitState() yielded.

    I hope I didn’t butcher the nomenclature about yields and coroutines:)

  • Scott
    January 18, 2013 - 1:29 am Reply

    Question for ya Mike —

    Been working on other stuff lately but coming back to my FSM now and coming across a bug/problem.

    I am using the code from the package above, with a couple tiny modifications (I added an overrideable OnUpdate routine and set it up to trigger along with the state.Update() call, just so I can have a little more control in my script). Other than that everything should be identical to the above package.

    I am finding that sometimes if a void-returning state function sets the currentState, and the set state is an IEnumerator-returning function, then the latter does not actually fire, i.e.:

    void LookAround_EnterState()
    {

    currentState = States.WanderAround
    }

    IEnumerator WanderAround_EnterState()
    {

    }

    Have you experienced this at all? If not, I’ll try to make a simple example project and send it your way. Hoping there was just a bug somewhere in the published code that you hadn’t submitted yet… :)

    • Scott
      January 28, 2013 - 7:48 pm Reply

      Running into another problem that seems similar.

      I am trying to use Call() to activate a substate, however the EnterState routine of the desired state is never called if the return type is IEnumerator — it must be void. Any idea whats going on? I thought the intent was that EnterState and ExitState could return either IEnumerator or void at any time, so long as the functionality was not being misused. Using Call() on an IEnumerator returning function should be possible, should it not?

      • Scott
        January 28, 2013 - 10:40 pm Reply

        Furthermore, this makes it impossible for me to wait for a Called state to finish before allowing the system to proceed. I am either missing something key about how to use the system, or something is amiss. Help!

      • Scott
        January 28, 2013 - 11:37 pm Reply

        Some code to reproduce the Call() bug, which is that suspension of the initial EnterState does not occur, as stated: “Suspend the current Enter coroutine”.

        TestCallBehaviour.cs
        *******************************************************************************
        using UnityEngine;
        using System.Collections;

        public enum TestCallStates
        {
        VoidState,
        EnumState,
        CallState
        }

        public class TestCallBehaviour : StateMachineBehaviourEx
        {
        void Start()
        {
        currentState = TestCallStates.EnumState;
        }

        void Update()
        {
        Debug.Log(currentState);
        }

        IEnumerator EnumState_EnterState()
        {
        Debug.Log(“Calling CallState from EnumState”);
        Call(TestCallStates.CallState);
        Debug.Log(“Just after Calling CallState from EnumState”);
        yield return null;
        }

        void VoidState_EnterState()
        {
        Debug.Log(“Calling CallState from VoidState”);
        Call(TestCallStates.CallState);
        Debug.Log(“Just after Calling CallState from VoidState”);
        }

        IEnumerator CallState_EnterState()
        {
        Debug.Log(“Waiting for 3 seconds in CallState”);
        yield return new WaitForSeconds(3f);

        Debug.Log(“Return()ing from CallState”);
        Return();
        }
        }

        *******************************************************************************
        Pastebin: http://pastebin.com/Sc2ZhiFK

        My apologies again for the spam. I really like this system you’ve created, it makes a lot of sense to me to code this way. If you could help me fix these problems I’d be incredibly grateful.

        • Scott
          April 11, 2013 - 1:59 am Reply

          Months later, the answer!

          Don’t define an Update routine in your derived class without running the base.Update() method! To make this a bit easier, I decided to “protect” (add the “protected” keyword) all MonoBehaviour functions in the FSM so that I receive a warning if I define them in my derived class. To remove the warning, I must write use the “new” keyword, and this is my reminder to call the base method.

    • Scott
      January 28, 2013 - 11:17 pm Reply

      Sorry for the spam. Thought I’d spend a few minutes writing some basic scripts to demonstrate the problems I have mentioned. Note that I am using Unity 4.0; if the problems stems from that, let me know. I may download Unity 3.0 and give it a whirl if time permit.

      Regarding void-states not executing enum-states:

      TestBehaviour.cs
      *******************************************************************
      using UnityEngine;
      using System.Collections;

      public enum TestStates
      {
      VoidState,
      EnumState
      }

      public class TestBehaviour : StateMachineBehaviourEx
      {
      public bool startWithVoidState = true;

      void Start()
      {
      // This state loop will fail when VoidState_EnterState sets the currentState to EnumState;
      // EnumState_EnterState() will never be run, nor the corresponding Update or ExitState routines.
      if (startWithVoidState)
      {
      Debug.Log(“initializing to VoidState”);
      currentState = TestStates.VoidState;
      }
      // This state loop will succeed until VoidState tries to execute EnumState, as before.
      else
      {
      Debug.Log(“initializing to EnumState”);
      currentState = TestStates.EnumState;
      }

      }

      void Update()
      {
      Debug.Log(currentState);
      }

      void VoidState_EnterState()
      {
      Debug.Log(“entered VoidState”);

      Debug.Log(“moving into EnumState”);
      currentState = TestStates.EnumState;
      }

      void VoidState_Update()
      {
      Debug.Log(“updating VoidState”);
      }

      void VoidState_ExitState()
      {
      Debug.Log(“exiting VoidState”);
      }

      IEnumerator EnumState_EnterState()
      {
      Debug.Log(“entered EnumState”);

      Debug.Log(“waiting for a second”);
      yield return new WaitForSeconds(1f);

      Debug.Log(“moving into VoidState”);
      currentState = TestStates.VoidState;
      }

      void EnumState_Update()
      {
      Debug.Log(“updating EnumState”);
      }

      void EnumState_ExitState()
      {
      Debug.Log(“exiting EnumState”);
      }
      }

      *******************************************************************

      • Scott
        January 28, 2013 - 11:19 pm Reply

        Because spam is delicious and color-coding helps comprehension, see the following pastebin link to the same C# code pasted in the previous comment:

        http://pastebin.com/gYgjrFXn

      • Scott
        April 11, 2013 - 2:01 am Reply

        And another answer, or possibly a work-around. Also, see the other problem’s answer about why there should not be an Update() function defined here.

        I still don’t know exactly why the Call behavior doesn’t work by itself, I thought it would be sufficient to place that line alone, but it is not, you need to “yield return null;” after it so that the system knows where to return to. Good to know.

        • Zeeawk
          May 12, 2013 - 6:03 pm Reply

          Scott, Have you figured out a solution to EnterState not being called?
          For me it’s is usually called but sometimes it doesn’t get called.

          I’m spawning a bunch of mobs and as I kill them they enter the Dead state, occasionally one will enter that state but Dead_EnterState will not run. Dead_UpdateState does run however.

          If you found a solution please post! Driving me nuts.

          Thanks!

          • Maxii
            February 7, 2014 - 9:51 pm

            Did anyone figure this out? I’m having the same problems – From a void EnterState method, Calling or simply assigning a new state where that new state has an IEnumerable EnterState method, results in the IEnumerable EnterState method not executing inside the Interruptable Enter Coroutine. I can see the IEnumerable EnterState method being sent to Run, but Run doesn’t appear to execute it.

            However, from my experimentation, it is only the first call or assignment from the void EnterState that fails. Subsequent calls or assignments to other states with IEnumerable EnterState methods are executed just fine.

            Any insights?

  • Terry Morgan
    January 21, 2013 - 3:40 pm Reply

    This should be on the showcase, it’s more fun than a lot of the ‘games’ I see there.

  • TB0Y298
    March 11, 2013 - 7:18 pm Reply

    I still dont get it how to “call” the F16. How does it work in this game?
    Please reply! (Via email is also allowed)

    I need your help!

    • whydoidoit
      March 11, 2013 - 7:27 pm Reply

      You need to pick up the targeting computer – then switch weapons to the laser pointer and paint a target with the laser until the timer runs out!

  • Iegor
    March 21, 2013 - 10:10 am Reply

    Hi, Great Example!
    I’ve started using your framework for my #1gam right away. Found one glitch so far and want to share to spread goodness,
    For OnTriggerStay state machine searches for “onTriggerEnter” method instead. This have confused me for some minutes, when everything else worked correctly.

  • agent
    April 11, 2013 - 2:33 pm Reply

    Nice article series and nice framework, just switched out my own (very simple, but effective) FSM framework for this.
    Noticed something which seemed a bit off, State_Update() is called (at least in my tests) once before State_EnterState()… Is this by design? And if so, why?

    Thanks for articles and the framework.

    • whydoidoit
      April 11, 2013 - 8:05 pm Reply

      Nope it shouldn’t be sounds like a bug – I’ll check it out.

      • agent
        April 11, 2013 - 11:09 pm Reply

        OK, great. If you can’t reproduce it I can create a project for you.

  • Mike
    April 17, 2013 - 8:44 pm Reply

    Great Series Thanks!

    I am seeing a problem that was mentioned in the comments of Part 2 in which

    When transitioning from state A to B
    B_EnterState is getting called before A_ExitState.

    You posted a reply stating that you added a line of code to the Run function of StateMachineBehaviourEx to fix the problem.

    I have downloaded the latest version and that line of code is NOT present in my StateMachineBehaviourEx.

    Did you fix this another way?

    • whydoidoit
      April 18, 2013 - 6:30 am Reply

      Oh hell – I look it out and post up the right version!

      • PabloAM
        April 18, 2013 - 3:42 pm Reply

        Do you have uploaded the right version?

      • Gazi Alankus
        April 19, 2013 - 6:44 am Reply

        It would be great if we could get this on github or something. I’m using your code in my Advanced Game Development class that I’m teaching and I’d love to contribute to the code in the future.

  • PabloAM
    April 19, 2013 - 12:20 pm Reply

    Hello. I´m having troubles.

    I have a Class called “Player” that inherits from “PlayerBase” and this class inherits from “StateMachineBehaviourEx”.

    I add “Player” script to a GameObject on the scene and in the Start of Player I call:

    currentState = PlayerBase.PlayerState.isChoosingN;

    The error that appears on console is:
    NullReferenceException: Object reference not set to an instance of an object
    StateMachineBehaviourEx.set_currentState (System.Object value) (at Assets/Scripts/StateMachineBehaviourEx.cs:707)
    Player.Start () (at Assets/Scripts/Common/Player.cs:142)

    What could be the problem?

    Thanks in advanced!

  • Zeeawk
    May 5, 2013 - 4:25 pm Reply

    Are you going to continue with the series?

    • whydoidoit
      May 5, 2013 - 5:28 pm Reply

      It’s my intention to continue this and A* – just paying work getting in the way :S

      • Zeeawk
        May 5, 2013 - 11:55 pm Reply

        pfft “paying work”
        If I had a nickle for everytime I heard that excuse! :P

        Seriously love your stuff. So much good info. Thanks so much for documenting it.

  • Zeeawk
    May 5, 2013 - 11:53 pm Reply

    Was having a problem with my model spinning around when I shot it. I made the change below and it seemed to fix it. I think what was happening is when setting _movePosition.position it was trying to rotate around and move to that position. I don’t really see why you need to do that. You only want the enemy to stop for a second while being hit.

    IEnumerator Hit_EnterState()
    {
    audio.PlayOneShot(hit);
    wasHit = true;
    _movePosition.enabled = false;
    //_movePosition.position = transform.position;
    animation.Stop();
    yield return PlayAnimation(“gothit”);
    _movePosition.enabled = true;
    Return();
    }

  • sumantri SQR
    May 7, 2013 - 1:05 am Reply

    Hi mike i try to make FSM that Control How the Object was Instantiate,
    i have GameObject that lies in Certain Area , Just like the Behaviour of NPC in COD . Here is my Brief idea , it’s just when NPC getting dead .
    1. My NPC sending message to the Instantiate Spot to Instantiate Particular character ,it will be Random.
    2. My Instantiate Spot Object then receive message.
    3. My Instantiate Spot Script determine a perimeter for NPC. The perimeters is where place The Npc Dead
    4. My Instantiate Spot Script then make an NPC Object which walk to the area where perimeter above was passed.
    that i dont Understand is, what i need a delegate when sending and receiving between My Instantiate Spot Script and NPC Script, or i just make NPC Script inherited from Instantiate Spot Script and then Overriding its Method? Thanks for all your Tutorials , they are helping me alot …. Sorry for my Grammar anyway
    regards :)

  • christian
    May 30, 2013 - 3:58 pm Reply

    have anyone figured out the ignored enterState issue yet?? help !!

  • Marco
    July 23, 2013 - 6:51 am Reply

    Hi everybody,

    I’m making a third person platform game which looks like crash bandicoot.
    I was wondering if i should use the FSM framework on my character. I’d like to use it to manage all the states (walk, run, jump, double jump, crouch, crawl, slide, powers…), but all the FSM example codes are used on NPC player.

    What do you think ?

    Thx

  • Jim Tang
    August 28, 2013 - 4:06 pm Reply

    I really appreciated your deep understanding of Unity coroutine mechanism, and it’s well explain by the Unity gems serials. But when it comes to implementing a hierarchical FSM system by using hijacked IEnumerator stack or something similar, I have to say something about using this framework.

    As an end user, just look at these:

    stateMachine.currentState = value; // two kinds of
    VS
    state.currentState = value; // got confused

    state.currentState = stateToActivate;
    state.executingStateMachine = useStateMachine; // machine and machine
    if (useStateMachine != this)
    {
    useStateMachine.stateMachine = this; // means nested state machine?
    }
    state.executingStateMachine.state.currentState = stateToActivate; // state -> machine -> state -> state, what does this really mean?

    public StateMachineBaseEx stateMachine; // always pointed to this?
    public StateMachineBaseEx lastStateMachineBehaviour; // what is the last one?

    public new Rigidbody rigidbody;
    public new GameObject gameObject; // many new members named by the base class members

    Compared with some classic FSM systems, I guess I know a little about your design ideas behind all these mess. Just name a few:

    1. State behaviours in a FSM should be static to all object instances, i.e., 100 monsters in a game always use a single FSM instance. So monster’s FSM is a static class which contains static member variables of some different State classes.

    2. State could be nested to construct a hierarchical FSM. Parent state may hand over the execution to its child states when entering, and child states must exit to return to its parent state. However deep the hierarchy is, there is only one single state is executing at the same time.

    3. Some NPCs could share same behaviours in some states. For example, a common following player AI state could be used by monster, sprite, boss, etc. So it’s a good idea to implement all state class independent of a specified kind of game object, instead, design abstract logic according to a serials of game objects to make states reusable.

    4. Unity MonoBehaviour class is very helpful for programming game logic. So it’s easy to do some simple FSM implementation based on it. But as the StateMachineBaseEx class already shown, it’s too big and complex to adding more contents into it now. it’s already beyond my comprehension.

    So I suggest just make the structure clear:
    1. Split StateMachine & State from GameObject & MonoBehaviour, using aggregation, not inheritance. If Machine class want to use GameObject or MonoBehaviour, just pass a ref to it.

    2. Make Transitions explicitly, it will be clearer to find all the transition definitions in a initialization function of a state class.

    3. I never use nor design a hierarchical FSM system, so I can not say which solution is better, but I think perhaps making states hierarchical is a good idea.

    Sorry for nagging a lot here, any other suggestions is very appreciated!

  • Maxii
    November 7, 2013 - 12:28 pm Reply

    Concerning .Net event wiring…

    From my experimentation and analysis of the code, unless I’m missing something (which happens more often than I’d like) :-( , I don’t think the following is a true statement:

    All scripts attached to the object will be searched for an event called EVENTNAME and any local methods called SOMESTATE_OnEVENTNAME with a compatible signature will be wired to them.

    Instead, I think it is:

    All scripts attached to the object will be searched for an event called EVENTNAME and any local methods called SOMESTATE_OnEVENTNAME_NAME with a compatible signature will be wired to them.

    Same thing goes for Tags and Child.

    The methodInfo elements that are captured in the code represent the Event Handlers with the full name of the method including the SELECTOR.

    I must admit I’m pretty confused as to how to make use of this event capability either way. Any ETA on the followup tutorial “how to use this to make a game”, and/or the full implementation of the model?

    Also, on the issue of entry and exit being out of order, the code I recently downloaded DID NOT contain the one line fix you indicated in InterruptableCoroutine.Run. I added it and it fixes the ordering…

  • Maxii
    November 9, 2013 - 11:11 am Reply

    RE:
    “Also, on the issue of entry and exit being out of order, the code I recently downloaded DID NOT contain the one line fix you indicated in InterruptableCoroutine.Run. I added it and it fixes the ordering…”

    Correction: the one line fix generated NREs so I removed it and wala!, I don’t see the entry/exit out of order issue anymore, which is why I guess, that the downloaded code doesn’t contain it. ….

  • Jack Al
    June 22, 2014 - 3:34 pm Reply

    Best Unity related site ever.
    FSMFinal2 error: Couldn’t decompress package

  • xra
    June 24, 2014 - 6:26 am Reply

    I’m getting an error when building standalone windows builds, any idea what this means?

    TypeDB: Class ‘StateMachineBehaviourEx’ was already registered, previous declaration was in ‘Assembly-CSharp.dll’ with 0 fields, current declaration is in ‘Assembly-CSharp.dll’ with 14 fields. Please check if your project doesn’t contain classes with duplicate names. For ex., non-generic ‘class MyClass’ and generic ‘class MyClass.
    UnityEditor.HostView:OnGUI()

    TypeDB: Class ‘StateMachineEx’ was already registered, previous declaration was in ‘Assembly-CSharp.dll’ with 0 fields, current declaration is in ‘Assembly-CSharp.dll’ with 4 fields. Please check if your project doesn’t contain classes with duplicate names. For ex., non-generic ‘class MyClass’ and generic ‘class MyClass.
    UnityEditor.HostView:OnGUI()

Leave a Reply

%d bloggers like this: