Go to Top

Moving from simple switch based FSMs to a delegate driven framework provides real power, this article shows the detail behind how to make it a reality.

Ah so you are back for round #2?  The first part of this tutorial was actually pretty straightforward stuff - in this section we are going to start to build our FSM framework so that we can write performant, neat code.

This part of the tutorial shows you how to build an FSM framework, if it gets too much don't worry, future sections will be less advanced and will cover how to design a game using FSMs.

It's a bit like you decided to by a new laptop and the salesman says,  "Great let me explain the silicon etching process used to build the processor! Don't worry it only takes about an hour."

After the first section this tutorial gets pretty advanced.  You might want to watch the video first to get a feel for it, but it's probably worth reverting back to the video later after reading the tutorial or a section of it.

Video

Tutorial Project

You can download the tutorial project from here.

Motivation

Our motivation for this part of the tutorial is to create something really powerful, a new way of writing code when you are implementing states that keeps everything clean.

  • Let states dictate their startup and exit conditions
  • Increase source code readability and reduce code indentation by having the individual routines broken out
  • Keep all of the code for a state together in the source file
To do that we are going to use some advanced techniques that mean that as well as the above benefits the code will also be faster than using endless if or switch statements.

State Setup & Tear Down

First lets think a bit more about states.  If we look at the code in our switch based example from #1 we will see that actually we hadn't completely managed to get all of the logic for our attack and hit states into one place.  The configuration, the setup, for the states had to be done inline where we set the currentState variable.  That's pretty obvious in the setting of the attack state:

			if( distanceSquared < _maximumAttackEffectRangeSquared && _angleToTarget < 60f)
			{
				//Set the current state
				currentState = EnemyStates.attacking;
				//Setup the animation
				_attack.enabled = true;
				_attack.time = 0;
				_attack.wrapMode = WrapMode.ClampForever;
				_attack.weight = 1;
				//Set a variable to make sure we know we
				//haven't inflicted damage yet
				hasStruckTarget = false;

				return;
			}

The attack state needs to wait for an animation, but the only place to configure that animation is when we set the state - the animation has to be running when we get into the Update function for the state.  But really we shouldn't need to know about  this stuff when we are effectively the client of the state - this code would need to be repeated in every place we started an attack.  Definitely not DRY.

In fact the routines in a state might look like this:

This diagram does not imply order of function calls.  Please note that OnGUI may well be called multiple times per frame.  FixedUpdate may be called more than once in a frame, or not at all, based on how fast the game is performing compared to the Physics fixedStep. 

So with this model a state is responsible for setting up its requirements when it is entered and tearing them down again when the state is exited.  The promise here is that Exit State code will execute no matter how or where we leave the state.  It's an important promise that will make our code much easier to write.

In fact some states are so simple that they could just do things in the Enter State, especially if that enter function was a coroutine that could execute over a few frames.  Using the model we are going to build in this part of the tutorial an attack state is just this:

	#region Attacking

	IEnumerator Attacking_EnterState()
	{
		//Setup the animation for attacking
		_attack.enabled = true;
		_attack.time = 0;
		_attack.weight = 1;
		//Wait for half way through the animation
		yield return StartCoroutine(WaitForAnimation(_attack, 0.5f));
		//Check if still in range
		if(target && (target.position - transform.position).sqrMagnitude < _maximumAttackEffectRangeSquared)
		{
			//Apply the damage
			target.SendMessage("TakeDamage", 1 + Random.value * 5, SendMessageOptions.DontRequireReceiver);
		}
		//Wait for the end of the animation
		yield return StartCoroutine(WaitForAnimation(_attack, 1f));
		//Turn off the animation's effects
		_attack.weight = 0;
		//Decide on the next state based on whether 
		//intended victim is alive or not
		currentState = target ? EnemyStates.Following : EnemyStates.Sleeping;
	}

	#endregion

One simple piece of code provides the setup and then the execution of the animation and damage provision.  We're back to something that is easy to comprehend in one page of the editor.

This next part is a pretty technical section - you could quite happily use the FSM framework built in this tutorial without knowing how it works.  A later article will concentrate on building a game using FSMs, so don't worry if you find this part too heavy going, it's just here so that those who want to know can learn about the techniques we use to build this tutorial.

It's All Done With Smoke & Mirrors

Ok it's time to lift the curtain and look at how we are actually going to build this FSM framework.  Here's the first big clue - delegates.

Delegates are like C/C++ function pointers, so if you come from that background think about them like this.
Part 1/Scene 3

It's time for some inheritance for our enemy controlling FSM - we are going to build a class called StateMachineBase that will actually be the underlying code that manages our states.

What we are going to do is have this new base class implement Update, OnTriggerEnter etc and have that implementation defer processing to a delegate, we will switch the delegates every time the state of the FSM changes.

What that means is that when, for example, Update is called on StateMachineBase it will delegate its processing to a delegate that represents the necessary functionality for the current state.  That delegate will be a routine in our derived class (our enemy) or it will be a default routine that does nothing.

	public Action DoUpdate = DoNothing;
	public Action DoLateUpdate = DoNothing;
	public Action DoFixedUpdate = DoNothing;
	public Action<Collider> DoOnTriggerEnter = DoNothingCollider;
	public Action<Collider> DoOnTriggerStay = DoNothingCollider;
	public Action<Collider> DoOnTriggerExit = DoNothingCollider;
	public Action<Collision> DoOnCollisionEnter = DoNothingCollision;
	public Action<Collision> DoOnCollisionStay = DoNothingCollision;
	public Action<Collision> DoOnCollisionExit = DoNothingCollision;
	public Action DoOnMouseEnter = DoNothing;
	public Action DoOnMouseUp = DoNothing;
	public Action DoOnMouseDown = DoNothing;
	public Action DoOnMouseOver = DoNothing;
	public Action DoOnMouseExit = DoNothing;
	public Action DoOnMouseDrag = DoNothing;
	public Action DoOnGUI = DoNothing;
	public Func<IEnumerator> ExitState = DoNothingCoroutine;

There they are - the delegates for our state machine. And here is the code that StateMachineBase uses to implement its Update method.

	void Update () 
	{
		DoUpdate();
	}
Delegates are basically function pointers, they are a variable that allows us to store a reference to a function that will be called when the variable in invoked.  So in this example DoUpdate() will be potentially a different function for each state of our FSM.

You may be used to writing event handlers in C# or another .NET language - those event handlers are implemented as delegates.

Here's a quick overview of why delegates are a good idea:

  • Delegates are very fast - they are pretty much the same speed as calling a function
  • By removing our switch statement we are no longer having to make a comparison for every possible state, so our code will run at the same speed no matter how many states we have
  • Delegates let us write code that uses reflection to find the routines for our states by the convention of calling them STATE_FUNCTION
Coding by convention is all about opinionated software - you should be used to that because Unity is already pretty opinionated.  You have to write an Update function with a capital U - there's no configuration to rename Update to be something else.  Convention based coding says you have to put things in the right place or name them the right thing and then the system will discover the functionality by scanning based on the convention that it has defined.
What we are going to do is reflect on the class that derives from StateMachineBase, in other words we will find the routines that match our functions.  In this section we are going to reflect upon the class each time we change the state.  Reflection is not at all fast - we will see how to cache the results in later parts of this tutorial - but we are only doing it during a transition so it will be fine for this first use.

Delegates

Ok so lets work through these delegates then.  .NET comes with two built in generic delegate types and you can also define your own, lets examine that method first.  For example here we define a delegate for a method that has no return value and takes a parameter of type Collider (like all of the OnTriggerXXX functions):

public delegate void UnityTriggerFunctionDelegate(Collider collider);

We could then define a variable that could point to a trigger function like this:

UnityTriggerFunctionDelegate _triggerFunc;

And we could assign it to a method in our class like this:

void Start()
{
    _triggerFunc = OnTriggerEnter;
}

void OnTriggerEnter(Collider collider)
{
     //Do something
}

You would then call it like this:

_triggerFunc(someColliderYouFound);

Which is equivalent to calling OnTriggerEnter(someColliderYouFound), but if you later switched _triggerFunc to point to OnTriggerExit then the _triggerFunc(someColliderYouFound) call would then be the same as OnTriggerExit(someColliderYouFound).

Rather than typing all of that delegate definition stuff each time you want to make one (which can be very confusing anyway as you can have multiple delegates that refer to the same method signature) .NET defines two generic delegate types: Action and Func.

So using these generic classes we can rewrite our variable definition for _triggerFunc and do away with the UnityTriggerFunctionDelegate definition all together.

Action<Collider> _triggerFunc;

The Action class defines a delegate to a method that returns void and the generic arguments are the parameters to the function.  So a delegate for a method that returned void and took a string and an int would look like this:

Action<string, int> variable;

The second type of built in generic delegate is Func the big difference being that the last generic argument is the return type of the function.  So a method that returns an int and takes a string would look like this:

Func<string, int> variable;
It's not normally necessary to define your own delegates these days, the generic ones are much easier to understand when you get used to them.

Reflection

Right then - if delegates are our "smoke" then reflection must provide the "mirrors" for our implementation - dada dum tish (I'm here all week folks...)

Reflection is the much maligned and misunderstood method of reading the metadata of classes when your code is running. Metadata you ask?  What I mean is that it gives you the ability to find all of the fields, properties, methods, parameters, return values of everything - even the private stuff.  More than that, not only can you find these items, you can also dynamically call them and change values.

Reflection often has a bit of a bad name - for one thing, it lets you break encapsulation; using reflection you can access all of the supposedly hidden and private members of a class!  At least you can if you have the security permissions and with Unity, you do have those permissions...  It's also a bit slow: slow to find things and then very slow to dynamically invoke them.

SendMessage in Unity uses reflection - that's why its between 85 and 150 times slower than firing an event using a delegate!

Used correctly reflection is a massive asset and in this section we're going to see how we can use reflection to create super fast delegates to the methods used to implement our FSM.

Our First Reflection

Ok so how do we do this reflection stuff then - well that's what .GetType() is all about on every single object in .NET - it lets you find the Type and the Type lets us find the methods, etc etc

void CallMethod(object target, string name)
{
       var mtd = target.GetType().GetMethod(name);
       if(mtd != null)
       {
          mtd.Invoke(target, null);
       }
}

Right, so what this does is it takes any object you pass to it, gets its Type and asks it to get a public method with the name passed in to our function - it does this by calling GetMethod.  That method is returned as a MethodInfo class which provides lots of information about the actual code. If there was a public method called name then mtd will not be null, the example then it calls this discovered method with no parameters by using Invoke and passing the object instance and null as the second parameter (indicating that there are no parameters).

You pass parameters to Invoke by putting them into an object[] and passing it as the second parameter.

You might use our example function like this:

CallMethod(yourScript, "SomeMethod");
This is a perfect example of reflection being super slow.  Invoke performance is terrible, finding the method every time is also not fast either.

By default GetMethod only lets you retrieve public instance methods, but you could find private methods and static methods using GetMethod too - there's a version which takes a BindingFlags parameter that lets you specify lots of options.

Getting fields by name is a matter of calling GetField and it won't take a rocket scientist to work out that the equivalent for properties is GetProperty.

The purpose of this tutorial is not to teach you everything about reflection though - just enough for us to achieve our goal of a fast, convention driven FSM framework.  For that all we need to do is access methods on a class.

Turning a Reflected Method Into a Delegate

Ok - so you've probably worked this out already but lets just summarise:

  • Delegates are really fast, but we need some way to discover the methods rather than manually assigning them
  • Reflection is really slow, but gives us a way to discover methods on our classes using a string
Wouldn't it be a good idea to turn our reflected MethodInfo instance into a delegate so that we could call it at maximum speed and only actually look it up when we need it to change?  Yep.

The Delegate class provides us with a static method called CreateDelegate that we can use to turn our reflected information into exactly what we need - a high performance delegate.

Now before we rush off and do that I want to take a moment to talk about a these delegates were going to create - there's a subtle fact here that you may well have missed.

An Action is a method with no parameters that returns no value.  Here's a class with two methods that could be assigned to Action.

public class ExampleClass
{

       public string somethingToLog;

       public void Log()
       {
            Debug.Log(somethingToLog);
       }

       public static void LogCurrentTime()
       {
            Debug.Log(Time.time.ToString());
       }

}

Yes both of those methods are suitable for Action, but one of them has access to the variables of the instance of the class and the other one doesn't.  How does the Action value know that?  The answer is a big topic in its own right; the answer is closures.

When you call an instance method of a class a hidden parameter is passed along to the function, it's the value that becomes this when you are inside your class method.  Of course when you write instance methods you don't have to specifically write this.somethingToLog - but you could - it means the same thing, the compiler is just filling it in for you.

So behind the scenes when you write someObject.SomeMethod() - the compiler is effectively doing this SomeObjectsClass.SomeMethod(someObject).

Basically what needs to happen is that the instance of the class is bound to the delegate we create in the case of the instance method, and not in the case of the static method.  After creating the delegate neither we nor the compiler will ever know whether this is a bound delegate or not, up until the point the code actually executes.

This is where delegates stop looking exactly like C/C++ function pointers, they have this added ability to bind in values.

So we can write this code:

Action someAction = instanceOfExampleClass.Log;

When we use that example code then the instanceOfExampleClass is tied into the delegate created for the Log method before it is stored in someAction; and from then on calling someAction() will always call the Log method on that particular instance.  It's hidden the reference to instanceOfExampleClass inside the delegate.

Of course we could write someAction = someOtherClassEntirely.SomeMethod() now calling someAction() calls that other class's instance method.  If we set it to the static method then we wouldn't need the instance reference at all, yet it would still work!

When we assign a delegate like the previous example we are always creating a closed delegate - we say it has been closed over the instance or (in the case of the static) just the type reference.

Let's take a minute to look at some other example of closures, because at the moment you are right on the brink of understanding the most powerful feature of delegates and while we only need to understand closed delegates for our FSM framework it would seem wrong to leave you teetering on edge of this knowledge.

There are actually things called Open Delegates that allow you to pass the this pointer at the time you invoke the delegate, basically making that hidden first this parameter visible to your code.  They can be useful in some circumstances, but we'll leave them for another day.

Closures

So you've seen how we can hide an instance reference inside a delegate to create a closure that means later on when we use the delegate we have no need to understand whether this Action is pointing to an instance member or a static member, or any need to know on what class this method exists.  All we need to know is that we can call someAction() and it will just work.

Here's the big news: you can hide other variables inside a closure too!

To do that you are going to use anonymous functions; in other words, a function that isn't actually a part of your class, and doesn't have a name, but can act just as if it were.  It's a function you define with code, or at least you define a bunch of its internal values and parameters with code.

Creating an anonymous function does not require a JIT compile and so works on all Unity platforms.

We know that Action defines a function that returns nothing and takes no parameters.  We know we can always call an action like this: someAction().

Let's create a little script that moves an object as a coroutine:

public static IEnumerator MoveThisObject(Transform objectToMove, Vector3 position, float period, Action onComplete)
{
      //We are going to use t to represent the amount to lerp 
      //each frame
      var t = 0f;
      //Record the current position of the object
      var startingPosition = objectToMove.position;
      //Loop while we aren't at the end
      while(t < 1)
      {
            //Lerp the object towards the target
            objectToMove.position = Vector3.Lerp(startingPosition, position, t);
            //Period is the time in seconds so we
            //divide Time.deltaTime by it to get the
            //amount to move this frame
            t += Time.deltaTime / period;
            //Yield until the next frame
            yield return null;
      }
      if(onComplete != null)
          onComplete();
}

So we have to start that script as a coroutine - The cool thing is the onComplete parameter - that's some function that will be called when the movement has finished.

Let's look at the easiest way of calling that function:

//We will use this inventory list in a while, it's basically
//a list of things you've picked up
List<SomeInventoryItemClass> myInventory = new List<SomeInventoryItemClass>();

void OnTriggerEnter(Collider other)
{
     if(other.tag == "Pickup")
     {
         //Move an object to our current position
         //over the period of 2 seconds
         StartCoroutine(MoveThisObject(other.transform, transform.position, 2, Finished));
     }
}

void Finished()
{
      Debug.Log("Got here");
}

Ok so that moves the pickup to our location over 2 seconds - but if we wanted to then destroy the pickup game object and add it to our inventory then that would be kind of difficult.  At the moment we have a lovely little function called MoveThisObject which would move anything anywhere - but how could we write Finished to actually destroy the object and add it to our inventory?

Are you thinking of setting some variables in the class that Finished would use?  That won't work, what happens if you pickup two things before the first one has finished?  You're stuck if you follow that approach.

So you might think the only way to actually do this is to write a new function that's called something like MoveThisObjectDestroyItAndAddItToMyInventory - hmmmm, a little less efficient if you have to write one of those for each of your functions.  Not very efficient and decidedly not DRY.

This is an ideal use for an anonymous function and a closure.  We are going to be able to keep MoveThisObject exactly as it is, yet be able to perform all of the actions we wanted.

Before we write our anonymous function let's just imagine what we would do if we just immediately picked up the object inside of the OnTriggerEnter and ignored our fancy movement coroutine.

void OnTriggerEnter(Collider other)
{
    //Is the collider a pickup
    if(other.tag == "Pickup")
    {
         //Get the script with the pickup information
         var pickupData = other.GetComponent<PickupItem>();
         //Add the item to our inventory
         myInventory.Add(pickupData.item);
         //Destroy the pickup object
         Destroy(pickupData.gameObject);
    }
}

Ok, its time for the best of both worlds - the best way to write an anonymous function in C# is to use lamba syntax - and I'm warning you, it looks kind of funky to start with.  Persevere and it will become natural.

void OnTriggerEnter(Collider other)
{
    //Is the collider a pickup
    if(other.tag == "Pickup")
    {
         //Move the object, when finished add it to the
         //inventory and delete it
         StartCoroutine(MoveThisObject(other.transform, transform.position, 2,
             ()=> {
                //Get the script with the pickup information
                var pickupData = other.GetComponent<PickupItem>();
                //Add the item to our inventory
                myInventory.Add(pickupData.item);
                //Destroy the pickup object
                Destroy(pickupData.gameObject);
             }));
    }
}

Just look what we've hidden inside a simple Action that can be called with someAction(). We've closed it over the other collider that was passed in as a parameter to OnTriggerEnter and we've also closed it over this which is needed to access myInventory.  If you entered a 1000 triggers at the same time, all of the objects would move to your position, be added to the inventory and be destroyed.  I don't know about you, but I think that's pretty cool.

You can pass parameters to lamba functions and return values too.  Imagine we defined a delegate like this:

//Define a delegate that takes 2 ints and returns an int
Func<int, int, int> someDelegate;

//Later

int result = someDelegate(4,4);

Now we could write these lambda functions:

//Lambda syntax with no code statements
someDelegate = (x,y) => x * y;

//The same thing as if it were a function
someDelegate = (x,y) => {
    return x*y;
};

//A different one
someDelegate = (a,b) => {
    var t = 0;
    for(var i = 0; i < b; i++)
    {
        t += a - i;
    }
    return t;
}; 

//One that closes over something else!
void CreateAFunction(int someValue)
{
     someDelegate = (a,b) => {
           return a * b / someValue;
     };
}

Never close a delegate over the iterator of a loop - that is a single instance of a variable and it will always contain the terminating value when the function is called.   When you need to do that you take a copy of the loop iterator into a local variable.

List<Action> resetPositions = new List<Action>();

void Start()
{
     //Loop through all of the children of this 
     //game object
     foreach(Transform child in transform)
     {
         //Take a copy of the iterator for closing
         var closeChild = child;
         //Get the position of the child
         var position = child.position;
         //Create a function to reset the position
         //and add it to the list
         resetPositions.Add(()=>closeChild.position=position);
     }
}

void ResetAllChildPositions()
{
     //Loop through our actions
     foreach(Action a in resetPositions)
     {
        //Reset the position
        a();
     }
}

There's a Eureka moment for closures. When you get it you find yourself grinning from ear to ear - suddenly your code gets a hell of lot more DRY.

Meanwhile Back at the Ranch

Ok, back to the plot - we need to build an FSM framework.  So to recap - we want to reflect to get methods and turn them into closed delegates.

So let's do just that.  We are going to write a generic method that can get a delegate from the name of the current state and name of the function that we want to execute.

We always store our states in an enumeration and all enumerations are derived from the system class Enum, so our StateMachineBase class defines a currentState variable of type Enum so that in the derived classes we can create any old enumeration we like and still be able to set it to currentState.  Moreover currentState will be a property so that we can write functions that cause something to happen as a side effect of setting it.  Like this:

	private Enum _currentState;

	public Enum currentState
	{
		get
		{
			return _currentState;
		}
		set
		{
			_currentState = value;
			ConfigureCurrentState();			
		}
	}

So whenever we set the currentState we are going to call ConfigureCurrentState() that's the thing that will setup our delegates.

Now you can always get the name of the value of an enumeration by doing, for example, currentState.ToString() - handy!

Here's ConfigureCurrentState(), note how we have some delegates that return coroutines for the Enter State and the Exit State functions.  As you can probably tell most of the magic is inside our generic method called ConfigureDelegate. We're passing it the name of the function we want, and a default value which is a delegate that fits the signature and does absolutely nothing.  If the configure delegate call doesn't find one in the matching state it will use the empty function instead.

	void ConfigureCurrentState()
	{
                //If we have an exit state, then start it as a 
                //coroutine
		if(ExitState != null)
		{
			StartCoroutine(ExitState());
		}
		//Now we need to configure all of the methods
		DoUpdate = ConfigureDelegate<Action>("Update", DoNothing);
		DoOnGUI = ConfigureDelegate<Action>("OnGUI", DoNothing);
		DoLateUpdate = ConfigureDelegate<Action>("LateUpdate", DoNothing);
		DoFixedUpdate = ConfigureDelegate<Action>("FixedUpdate", DoNothing);
		DoOnMouseUp = ConfigureDelegate<Action>("OnMouseUp", DoNothing);
		DoOnMouseDown = ConfigureDelegate<Action>("OnMouseDown", DoNothing);
		DoOnMouseEnter = ConfigureDelegate<Action>("OnMouseEnter", DoNothing);
		DoOnMouseExit = ConfigureDelegate<Action>("OnMouseExit", DoNothing);
		DoOnMouseDrag = ConfigureDelegate<Action>("OnMouseDrag", DoNothing);
		DoOnMouseOver = ConfigureDelegate<Action>("OnMouseOver", DoNothing);
		DoOnTriggerEnter = ConfigureDelegate<Action<Collider>>("OnTriggerEnter", DoNothingCollider);
		DoOnTriggerExit = ConfigureDelegate<Action<Collider>>("OnTriggerExir", DoNothingCollider);
		DoOnTriggerStay = ConfigureDelegate<Action<Collider>>("OnTriggerEnter", DoNothingCollider);
		DoOnCollisionEnter = ConfigureDelegate<Action<Collision>>("OnCollisionEnter", DoNothingCollision);
		DoOnCollisionExit = ConfigureDelegate<Action<Collision>>("OnCollisionExit", DoNothingCollision);
		DoOnCollisionStay = ConfigureDelegate<Action<Collision>>("OnCollisionStay", DoNothingCollision);
		Func<IEnumerator> enterState = ConfigureDelegate<Func<IEnumerator>>("EnterState", DoNothingCoroutine);
		ExitState = ConfigureDelegate<Func<IEnumerator>>("ExitState", DoNothingCoroutine);
                //Optimisation, turn off GUI if we don't
                //have an OnGUI method
		EnableGUI();
                //Start the current state
		StartCoroutine(enterState());

	}

Ok so as you can see we have set each of our delegates, let's see how ConfigureDelegate works:

//Define a generic method that returns a delegate
//Note the where clause - we need to ensure that the
//type passed in is a class and not a value type or our
//cast (As T) will not work
T ConfigureDelegate<T>(string methodRoot, T Default) where T : class
	{
                //Find a method called CURRENTSTATE_METHODROOT
                //The method can be either public or private
		var mtd = GetType().GetMethod(_currentState.ToString() + "_" + methodRoot, System.Reflection.BindingFlags.Instance 
			| System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.InvokeMethod);
		//If we found a method
		if(mtd != null)
		{
                        //Create a delegate of the type that this
                        //generic instance needs and cast it                    
			return Delegate.CreateDelegate(typeof(T), this, mtd) as T;
		}
		else
		{
			//If we didn't find a method return the default
			return Default;
		}

	}
In the next section of this tutorial we will build a much more efficient version of this routine that caches the delegates found, there's a good reason for this.  Just creating that string in the GetMethod call is allocating memory that will lead to garbage collection cycles.  But for now this is a fully functioning example and none of the principles will change.
At present our Enter and Exit functions have to be enumerators.  We'll change this requirement later, but for now you would have to have a yield return null or yield break in the functions even if you didn't want them to be coroutines.  A minor irritant, but one we will fix in the next sections.

Conclusion

I'll leave it to you to look through the code in FiniteStateMachine2 or you can review it with me in the video below.  There are a few other features of StateMachineBase like waiting for animations and caching of common variables like transform,  but we'll leave those to next time where they really come into play when we start injecting states into remote objects!

I know this has been a technical and rather advanced part - please remember, it's going to get easier again when the state machine system is finished.

Video

You might want to watch the video again now.  Actually you might want a stiff drink or whatever form of distraction that your culture deems acceptable :)

, , , , , , , ,

45 Responses to "Finite State Machines #2 – Delegates, Reflection & Closures"

  • Dio
    November 6, 2012 - 9:47 pm Reply

    Very good post!
    I consider myself a newbie programmer. Your tutorials are very useful. Recently I’ve been digging into them and try fully understand them.
    I would appreciate a lot if you could introduce something about multiplayer game development using Unity. Actually I know nothing about how to setup a server nor any php stuff. And also little knowledge about the network API in Unity.

  • Valentin
    November 7, 2012 - 9:58 am Reply

    This fsm implementation might be good for everyday simple state machines but it has at least three obvious drawbacks:
    1. I have to subclass StateMachineBase for every state machine I need which might be not possible even in case of MonoBehaviours. And I usually have many FSMs outside of MonoBehaviours.
    2. While processing events you still have to use a lot of switch case currentState code.
    3. Passing a parameter to a state_enter is hard. For example when I have a book I want a state OpenedAtPage(int pageNum). With current implementation I will have to set a property nextPage before changing state to FlipToPage instead of more elegant state = FlipToPage(42) or alike.

  • whydoidoit
    November 7, 2012 - 10:16 am Reply

    This is going to be quite a long series – as I’m effectively teaching how to build a framework and then use it…

    1. In my full implementation of this I have a base state machine class that does not inherit from MonoBehaviour, I have a StatefulBehaviour that delegates to it. This will be introduced at the end of the series.

    2. The implementation in the project supports that by using a delegated SendMessage, that will be introduced in the next part of series. The final chapter where I introduce the complete framework uses the same principle for .NET events as it does for Update etc which makes them very easy to implement differently for each state.

    3. You could handle that in a couple of ways – in my (very complicated!) game I tend to use a state change function that can have parameters – but the paradigm of setting a variable (property) is simpler and much more like the traditional state machine switch statement approach. At the end of the day its the trade off between having to configure a parameter and having a clearly defined and immediately visible set of states that are kept together. It would depend on how often you pass parameters to states whether you decided to implement currentState as a struct or class that contained perhaps a hash of parameters that would be turned into named parameters in the function call.

    • Valentin
      November 7, 2012 - 10:44 am Reply

      > I have a StatefulBehaviour that delegates to it.
      So you have to subclass it anyway. If my Unity development framework uses let’s call it AdvancedMonoBehaviour : MonoBehaviour I can’t use your fsm implementation, right?

      > by using a delegated SendMessage
      So you would have to call some SendMessage method in every event listener? Probably with an EventArgs parameter which forwards this call to a CurrentState_MyMessage(EventArgs params) method?

      > At the end of the day its the trade off between having to configure a parameter and having a clearly defined and immediately visible set of states that are kept together.
      BookAtPage(int) is a clearly defined state. How else would you implement it?

      In everyday life in most statemachines there is at least one state with a parameter.

  • whydoidoit
    November 7, 2012 - 10:19 am Reply

    Actually I should probably say that in my game I use the principle of Blackboarding – where states access a common *blackboard* that contains the parameters they need and are activated for a particular task based on their *vote* of how well they can achieve it.

    • Valentin
      November 7, 2012 - 10:49 am Reply

      Like a separate object which holds parameters not to clutter up the main class?

      I actually had been thinking about fsms for a very long time. Made a couple of frameworks which let you set up a fsm to use. I used enums, strings, objects as states. I tried keeping state-related data in such an object and pass it around as a boxed state. And much more. But eventually came up to a simple coding convention which doesn’t bring a framework with it, which is fast and easy to use. But I still like reading how other people implement fsms. Getting cool ideas from such posts but still don’t see myself using most of them.

      • Tim
        November 8, 2012 - 2:50 pm Reply

        Valentin, I’ve gone through several FSMs and have not yet found one that I’m completely happy with. I am curious on your simple coding convention. Would it be possible to get an example project using it? Or just some code snippets if it’s that simple? Thanks

  • whydoidoit
    November 7, 2012 - 11:12 am Reply

    Yeah I understand that – that’s actually why I wanted to write a tutorial on implementing a state machine framework – because the ideas behind it might be useful in lots of places, even if you don’t use the finished article…

    It’s actually a push though, because part of this tutorial is really about getting people to think in states too. Hopefully it will be clearer when I’ve finished it :)

    • Valentin
      November 7, 2012 - 12:00 pm Reply

      Keep the good work! q:
      I liked your other articles about shaders.

    • whydoidoit
      November 24, 2012 - 12:41 am Reply

      Yeah I like it :) I started off that way myself (in fact my real version of the FSM has that and the delegate/reflection/closure stuff is an implementation of my IState interface – I just wrote it straight for the article to teach about those methods).

      The reasons why I pretty much never write an IState implementation now though is that you need to teach it a lot about the game object that it is a part of – that takes a bunch of initialisation code and you end up with a lot of “through” references to the variables on the attached script. So for me, I prefer not to have the clutter and dereference performance of the classes and that extra code – but it’s a totally valid approach and allows swapping in states easily.

      So I like the closure/delegate/reflection approach because it does this:

      • Keeps the code looking like Unity code
      • Keeps the code together with all of the variables of the class
      • Doesn’t require me to add extra functions to my interface to add extra calls (like SendMessages) or other things like auto event wireup
      • Doesn’t force me to implement methods that I don’t use.
      • Is as fast as a vtable lookup of an interface override. Potentially faster for unused methods with a null check.
  • mick
    November 29, 2012 - 12:12 am Reply

    I’m kind of shocked to see that when you transition from one state to another, say from A to B, that B_EnterState will be called before A_ExitState. My test can be seen here: http://pastebin.com/yLaS1zZB

  • whydoidoit
    November 29, 2012 - 7:25 am Reply

    Very good spot mick – I totally forgot the code to run the coroutine once before handing it over to the normal processing (which is why exit is called after enter) – it should of course be executed immediately as well and it wasn’t happening. Need to modify this code from InterruptableCoroutine in StateMachineBehaviourEx:

    		/// <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();
    			}
                            //NEW LINE
    			enm.MoveNext();
    			
    		}
    
    • Maxii
      November 8, 2013 - 3:47 pm Reply

      With this new line, I’m getting Null Reference Exceptions inside MoveNext() when I use an exit state that returns void rather than an IEnumerator. I was under the impression that Enter and Exit didn’t have to be coroutine compatible methods any more…

  • whydoidoit
    November 29, 2012 - 7:30 am Reply

    I am uploading a replacement with that line fixed in it – will post here when the upload is complete

  • whydoidoit
    November 29, 2012 - 4:22 pm Reply

    Fully uploaded now

  • Jay
    January 10, 2013 - 10:10 pm Reply

    Thanks for these tutorials :) This is my first time trying to understand delegates and abstract functions and I think you did a good job of it, but I have to say its the hardest topic I’ve encountered yet! Quite a lot to keep in your head all at the same time.

    I’m going through this line by line, and the first thing I don’t totally understand lies in very beginning of the abstract base class. What is the purpose of public new Transform, public new Rigidbody, etc?

    I’m guessing its to cache these variables and I can see they are used in the inherited FSM classes, but why the new operation and using base.transform etc? What purpose is this serving?

  • whydoidoit
    January 11, 2013 - 6:59 pm Reply

    So I’m just really creating cached copies of the properties for the standard transform, rigidbody etc so that they are faster to access, given that most people like to use the original names this just ensures better performance by turning them from internal GetComponent calls to simple variables.

  • gribbly
    January 26, 2013 - 5:29 am Reply

    Just wanted to say thanks for the tutorial, I finally got my head wrapped around delegates and I have a working FSM based on your code!

  • Jay
    January 27, 2013 - 3:11 am Reply

    Okay, I get the cached copy thing. I’ve got this up and working now, its awesome.

    One thing though, what do you recommend doing in networked situations? In my case I’ve just got players (no NPCs) and I’m having a tough time thinking up a way to integrate this with Network.Instantiate because my prefabs all get controlled at the same time. It would ruin the elegance of this whole thing if I had to put if(isControllable) at the start of every function.,

  • Jay
    January 31, 2013 - 8:25 am Reply

    Man, I really gotta say, this is the best state machine implementation ever. Thank you so much for putting this out there. It took me a while to learn the ins and outs but now I see that it is incredibly powerful!

  • PallidFingers
    February 20, 2013 - 7:14 am Reply

    I love this! :) Pro Coding! Thank you so much! I am learning a lot! am really reallly happy :’)

  • Benoit FOULETIER
    May 6, 2013 - 9:04 am Reply

    Wow… for a beginner tutorial, it seems waaaaay convoluted!! Inheritance would seem so much simpler (a base State class, or an interface but with a class you don’t have to override everything), and as you said in another comment, what you’re effectively doing is reinventing the vf_table!
    The only minor bonus I see here is I suppose a state can implement any callback either as a coroutine or a straight method… seems slim! Although with a class a normal method just has to wrap a coroutine inside a StartCoroutine(() => {…}); and voilà. Btw all those closures ain’t free you know!
    I’m not saying your approach isn’t interesting, it’s just a) I fail to see the necessity, and b) boy I would never recommend a beginner to start with this!

    One last thing I must point out that is just plain incorrect: the cost of a switch over an enum does NOT depend on the number of values in the enum! that’s what’s so great about switch, it’s basically free. See jump tables or branch table: http://en.wikipedia.org/wiki/Branch_table
    So if your enum has 10 values, a switch costs as much as one branch (~ one if), not 10 branches.

  • whydoidoit
    May 6, 2013 - 9:22 am Reply

    Firstly this tutorial is not for beginners :)

    The cost of a delegate is significantly less than the cost of bothering to do any part of a switch and makes the code far more legible in my book. I am aware that closures aren’t free and have impirically tested the performance.

    Inheriting a class for each state makes reading parallel state machines very hard as its difficult to see which component is related to each other one. Multiple classes (not inheriting for MonoBehaviour requires lots of copied variables and static class references which I can live without!)

    I find this to fit well with the normal model of coding Unity and produces highly legible modules which are easy to follow and debug. But we’ll, that’s just me!

    • Benoit FOULETIER
      May 6, 2013 - 9:41 am Reply

      Hey I’m not saying go with an enum/switch-based FSM, I’m just saying it doesn’t cost as much as the number of states (you mentioned “comparison with every possible state”).

      And, regarding legibility, I’m not suggesting to have one MonoBehavior per state, the states can be nested classes inside of the main FSM. This way you share what you want in the main, and each state can keep its internal stuff nicely encapsulated if it needs to, override only the callbacks it needs, etc. The main will only ever need to call currentState.Update() etc, so roughly the same cost as a delegate I’d guess.

      Again, it’s just that the benefits seem slim… method names are open to typos… plus doesn’t reflecting & caching all the delegates increase load time? (& mem usage but let’s not be picky ;)
      I guess my point is, what does an inheritance approach NOT provide?

  • whydoidoit
    May 6, 2013 - 10:18 am Reply

    No you’re right, I’d forgotten optimisations for enum switches.

    So I built an inheritance framework first and I built this because it improves the speed of my programming and reduces the number of errors I make. Given I’m used to having to write special “convention” methods in Unity I don’t find a significant problem to write them correctly.

    * Multiple classes with the same method names, requires checking as to which class you are in, or they are in separate files and the logical flow is split between multiple panes. I prefer convention over inheritance in this circumstance.

    * Sharing variables between states is easy and doesn’t require a deep and constantly refactored inheritance structure.

    Of course this method is very similar to the one that Unity is providing in it’s standard uses of Update, OnColllisionXXX etc.

  • Ronaldo
    May 10, 2013 - 5:05 pm Reply

    Hey, great tutorial series. I am still striving to understand everything. But I must say, even the usage of the framework is still confusing to me. I am not complaining, since this framework is free ;) I consider myself an intermediate to advanced Unity programmer, and I am looking for a simple but efficient FSM framework to use. Don’t know how to qualify yours yet.. =/

  • whydoidoit
    May 11, 2013 - 8:42 am Reply

    Well this is a tricky section :)

  • Zeeawk
    May 12, 2013 - 11:40 pm Reply

    Is StateMachineBehaviourEx the most recent version of the state machine?

    I’m having a problem when I set state to Dead occasionally the Dead_EnterState doesn’t get called.

    I assigned each of my spawned objects an ID and then printed a debug message as the first line in Dead_EnterState with the ID. When the problem occurs I do not see the ID message printed.

    I’m probably spawning about 45 objects. When the problem occurs (so far) it only happens to one object out of the group.

    Dead_UpdateState gets called and if I set a breakpoint in there I can see that Dead_EnterState is setup as a method to be called but for some reason it doesn’t get called.

    It doesn’t happen every time so it’s pretty difficult to track down.

    Any thoughts?

    • zlanemerennah
      June 5, 2013 - 2:14 pm Reply

      Your ExitState is a coroutine? According to implementation it launches and should be like state exit condition – not a callback upon state change as i thought earlier. I have something like this now :


      IEnumerator DamageRecieved_ExitState(){

      yield return new WaitForSeconds(damageRecievedDuration);

      currentState = stateBeforeDamage;

      }

      correct me if i’m wrong, whydoidoit

  • mcTeapot
    September 4, 2013 - 11:06 am Reply

    Great tutorial, brought a tear to my eye knowing that I can now code C# with Anonymous Functions.

  • Luke Craig
    December 22, 2013 - 11:49 am Reply

    I believe I found a typo in StateMachineBase.cs. On line 105 it says “OnTriggerExir” instead of “OnTriggerExit”

    Thanks for the tutorial, it’s very helpful.

  • Lee
    February 9, 2014 - 7:05 pm Reply

    Lovely tutorials, upping my game for sure :)

  • rpilcher
    April 14, 2014 - 6:29 pm Reply

    Hello

    I’m having an issue decompressing the tutorial project package. I’m using Unity Pro 4.3.1.

    Any ideas?

  • Ryks
    April 20, 2014 - 5:52 am Reply

    Greetings whydoidoit, and thank you for explaining all of this. Very well done. Your deserving of this[https://www.youtube.com/watch?v=EQEZGzIOblo].

    In the ConfigureCurrentState() you send the DoNothing Delegate if one of the state functions isn’t defined. However doesn’t this create a whole slew of empty / DoNothing Delegates for our states?

    I know you said Delegates are fast, but doesn’t this have an impact? I read all of the comments and if I remember right someone said there was a memory impact, would this be because of the slew of DoNothing Delegates for the state that we haven’t defined?

    Also this led me to wondering does MonoBehavior then have the same characteristic then?

    • whydoidoit
      April 22, 2014 - 1:18 pm Reply

      There is “very little” overhead for this – tiny compared to a lot of things that might be used in code. Calling DoNothing for nothing takes a small amount of time (creating a stack frame, moving the instruction pointer, resetting it and then unwinding the stack frame) but it makes the coding a bit cleaner to my mind and as these things aren’t being called in some horrendous loop there will be no obvious difference in performance.

  • Jon Hon
    July 17, 2014 - 5:44 pm Reply

    Thanks for posting this excellent series of articles. I’m going to be using a FSM to control the tutorial levels for my Ball Cats 2 game.

    There is a typo in your article here…

    “talk about a these delegates were going to create”

    should be

    “alk about these delegates we’re going to create”

  • TimeLine | Caracteres no jugables (NPC)
    July 31, 2014 - 4:57 pm Reply

    […] y algo complicado tutorial de Maquinas de Estado Finitas (FSM) en Unitygems.com (Parte1 – Parte2 – Parte3) he decidido usar su framework basado en delegates para mis […]

  • Varun V P
    August 28, 2014 - 1:33 pm Reply

    Woah!!! Nice tutorial…. Still trying to understand it. I wanted to know if fsm frameworks are powerful enough to run on mobile platforms(android). Or should we stick to switch statements?

    • whydoidoit
      September 4, 2014 - 6:36 pm Reply

      FSMs are super fast on mobile – I only write mobile games myself.

  • Varun V P
    August 30, 2014 - 3:02 pm Reply

    ………..And one more question? Do we need to have a seperate StateMachineBase for every AI Script for every GameObject? Or could we just derive every FSM script from the one StateMachineBase?

  • Juhani Karlsson
    September 19, 2014 - 5:40 pm Reply

    I have read this kazillion times and I`m still confused : D not the easiest topic.
    I dont`t understand why there is explanation for many ways of creating delegate. Now I`m just lost.. uhhh..

    Anyway its great tutorial. I just need to bang my head against this…
    Thanks,
    - J

Leave a Reply

%d bloggers like this: