Partial Class State Machine

You’ve probably been told before not to re-invent the wheel, but when it comes to my own code I couldn’t disagree more. I love re-inventing the wheel because it helps you understand why things are designed the way they are, and occasionally allows you to make something better. I’m currently “thinking out loud” about a whole new approach to the way I implement state machines that can provide functionality I had been wanting but not thought was possible – until now.

The Problem

You can see State Machine’s used in a lot of my code. In particular I make use of them in the Tactics RPG and Tic Tac Toe projects. The StateMachine and the State scripts are all MonoBehaviour subclasses which allows me to use things like GetComponent and AddComponent to make getting and changing state nice and easy. In addition, I could use MonoBehaviour abilities like Coroutines, or the ability to grab other components attached to the same GameObject. I felt like I had a whole host of beneficial and powerful features with my original architecture. Still, I always felt like something was missing, or just not right. Perhaps it just wasn’t as good as it could be.

My primary complaint was that the whole architecture was based on “has a” rather than “is a”, and what I mean by this is that my object, say a “Game Controller”, has a “State Machine”, and it has several “State” components. So for example, when it comes time to perform “setup” on the “Game Controller” then I could create a special state for this task. However, the “Setup State” is its own object instantiated from its own class. It needs to know about its owner, but can only see what the owner exposes in the interface. In order to expose something to the state, it would also become exposed to everything else. Wouldn’t it be nice if the setup state could somehow have special privileges or permissions to see private fields or access private methods on the owner which other classes could not see?

Even when a state only needs access to things which are already public, I still have to refer to them in the sense of the owner. For example, if a state refers to the Game Controller’s hero, it might need to use something like “owner.hero” instead of just “hero”. This would either end up making all of the code a little longer, or would require patterns such as convience wrappers. I often used the later approach and would make a common base class that my other states would inherit from. This class would automatically cache the owner, and use properties to wrap the owner’s fields and properties as if it were its own.

Both of my primary complaints would be solved if I could think of the state as an “is a” instead of a “has a”. This would mean that the “state” ought to be able to act as if it was actually the “owner”. This would give me direct access to all fields, properties, and methods, etc, regardless of if they were public or private. This was a big challenge though because I had to keep several things in mind:

  • I still want to keep the “state as an object” pattern, so I can determine when state changes and act on it. If the owner is the state, there is no object change when a state changes.
  • There are no C++ style “friends” in C#. The only way to access something private is to be the class itself or to be defined inside the class, such as an embedded class. This option wouldn’t be compatible with a Monobehaviour.
  • I still need a common interface so that the state machine can act at a lower abstract level. I just want “Enter” and “Exit” methods.
  • I can use extensions on a class, but can only use methods, and can’t add new fields which might be needed to properly maintain the state. I also can’t keep re-defining the same method names needed by the state machine interface for multiple different states.

The Solution

I decided that I could “inject” the functionality I wanted. By making a state a simple container for “action” methods, I could still have separate objects for each state. I could maintain a common abstract enterface with “Enter” and “Exit” calls. I could even, in a way, allow a state to act as the owner itself and have full access to everything, even all private details (really it is the delegate that had access). I took it a step further, and made the owner a partial class, with separate definitions for each state in its own file. Because of this, I can also maintain clean and simple code where all of the logic unique to a state was organized nicely on its own.

Want to see what this looks all like with actual code? Glad you asked!

State

using UnityEngine;
using System;
using System.Collections;

public class State
{
	#region Fields
	public Action Enter;
	public Action Exit;
	#endregion

	#region Factory Methods
	public static State Empty ()
	{
		return new State(DoNothing, DoNothing);
	}

	public static State EnterOnly (Action enter)
	{
		return new State(enter, DoNothing);
	}

	public static State ExitOnly (Action exit)
	{
		return new State(DoNothing, exit);
	}
	#endregion

	#region Constructor
	public State (Action enter, Action exit)
	{
		Enter = enter;
		Exit = exit;
	}
	#endregion

	#region Private
	static void DoNothing ()
	{
		
	}
	#endregion
}

Here’s the State class. See how it isn’t an abstract base class? With this new architecture, I don’t expect to actually create subclasses of State, but will probably always use them as simple “dumb” containers. The only expected purpose of the object is to hold the references to the two “Action” delegates, “Enter” and “Exit”.

I created a few convenience Factory Methods just in case you wanted a state that didn’t implement one or both of the actions. The constructor expects both actions – neither action should ever be “null”. I also created a static method called DoNothing, that (surprise) doesn’t do anything. This will be the default method for any state that doesn’t need to be fully implemented.

State Machine

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

[Serializable]
public class StateMachine
{
	string current = string.Empty;
	Dictionary<string, State> states = new Dictionary<string, State>();

	public State CurrentState
	{
		get
		{
			return states.ContainsKey(current) ? states[current] : null;
		}
	}

	public void Register (string key, State state)
	{
		if (!string.IsNullOrEmpty(key) && state != null)
			states[key] = state;
	}

	public void Unregister (string key)
	{
		if (string.Equals(key, current))
			ChangeState(string.Empty);
		
		if (states.ContainsKey(key))
			states.Remove(key);
	}

	public void Clear ()
	{
		ChangeState(string.Empty);
		states.Clear();
	}

	public void ChangeState (string key)
	{
		if (string.Equals(key, current) || key == null)
			return;

		if (states.ContainsKey(current))
			states[current].Exit();

		current = key;

		if (states.ContainsKey(current))
			states[current].Enter();
	}
}

I also decided not to make the state machine a subclass of MonoBehaviour. I don’t actually “need” to, because functionality you would need can be injected directly into the state. Note that I also tagged this class as Serializable even though I have no serialized or public fields. If you look at the upper right corner of the Inspector pane, just to the right of the lock icon, is a hamburger looking menu button. You can use this to switch between “Normal” and “Debug” modes, but while in Debug, you will actually be able to see the private fields of your objects. Any Monobehaviour which has a state machine (even a private one) would then appear in the inspector, and you would be able to read the name of the current state field as well.

Since I am not using MonoBehaviour based states, I need something to be able to maintain all of the state references so I can easily switch back and forth between them. I decided to use a Dictionary for this which maps from a string “key” to an instance of a State “value”. The dictionary is also private so you will be required to use the “Register” and “Unregister” methods which provides me a chance for a little error handling. If you need to clean up, you can use a simple “Clear” method to remove all states from the machine. Note that when I unregister or clear, it will first “Exit” the current state if applicable.

The ChangeState method will be used the most. It expects a “key” to know which state to transition to. This also means you must have already registered the state by that key. The method checks to make sure that you aren’t attempting to change to the current state, and will exit early in that condition. It also checks to make sure you don’t pass a “null” value for the key, becuase that isn’t compatible with the dictionary. When transitioning from one state to another, I always give the original state the opportunity to “Exit” before allowing the new state the opportunity to “Enter”.

Demo Consumer

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public partial class BattleController : MonoBehaviour 
{
	#region Fields
	StateMachine _stateMachine = new StateMachine();
	int _aNumber;
	bool _aBool;
	#endregion

	#region MonoBehaviour
	void Awake ()
	{
		RegisterStates();
		_stateMachine.ChangeState(ActiveState);
	}

	void OnDestroy ()
	{
		_stateMachine.Clear();
	}
	#endregion

	#region Private
	void RegisterStates ()
	{
		_stateMachine.Register(ActiveState, new State(ActiveStateEnter, ActiveStateExit));
		_stateMachine.Register(PassiveState, new State(PassiveStateEnter, PassiveStateExit));
	}
	#endregion
}

Here is the first part of a class which consumes our State Machine code. It is a MonoBehaviour but is defined as a partial class – this still works, you just have to make sure that when you connect a script to an object that the name of the file matches the name of the class.

This demo doesn’t actually do anything, it simply demonstrates how to create a few states which can see and directly act on the members of the owner. All of the fields are left implicitly private to help re-iterate the flexibility of this approach.

In the “Awake” method, I register all of the potential states that my implementation could need, and then change state to one of them. In the “Destroy” method, I clear all the states, which isn’t strictly necessary, but I like to clean up after myself.

The RegisterStates method references strings and methods which aren’t defined anywhere you can see yet. Don’t forget that the class is defined as “partial” – you will see them in another file.

using UnityEngine;
using System.Collections;

public partial class BattleController : MonoBehaviour 
{
	public const string ActiveState = "Active";

	void ActiveStateEnter ()
	{
		_aNumber++;
		_stateMachine.ChangeState(PassiveState);
	}

	void ActiveStateExit ()
	{
		if (_aNumber >= 10)
			_aNumber = 0;
	}
}

This code exists in another file named “BattleControllerActive.cs” even though the name of the class is still “BattleController”. Don’t forget that you must include the “partial” keyword in the definition of this class or the compiler will complain at you. Note that you can’t add this file to GameObjects in the Unity Editor, but any fields you define here can still be visible in the inspector as part of the BattleController component.

Within the same class (even a partial class) I can’t redefine a method with a same name as another method. This means I can’t have two “Enter” methods, but I can use a sort of naming convention like I did here. I am treating this partial class as if it were a state called “ActiveState” so I use that as a prefix on the “Enter” and “Exit” methods I actually wanted.

Inside of these methods I “work” with the private properties defined in the original partial class file, even though I am not really doing anything useful. It is just placeholder code to show that I can do stuff. Cool huh?

using UnityEngine;
using System.Collections;

public partial class BattleController : MonoBehaviour 
{
	public const string PassiveState = "Passive";

	void PassiveStateEnter ()
	{
		_aBool = true;
	}

	void PassiveStateExit ()
	{
		_aBool = false;
	}
}

Like before, this code exists in yet another file named “BattleControllerPassive.cs” even though the name of the class is still “BattleController”. I use the same sort of naming convention as I did in the “ActiveState” version, and I modify one of the other private fields just for fun.

Summary

In this lesson I “thought out loud” about some new architecture I intend to add to my future projects as a replacement for my old State Machine code. With the new architecture, states no longer need a reference to their owner, because they act using code injected from the owner itself. This allows direct access to anything and everything, without needing to also expose access to any other classes.

Note that I haven’t battle tested my ideas yet, so I don’t actually know how much I do or don’t like it. At the moment I feel like I will love it, but until I try working with it in a “real” project (or three) it can be hard to tell the full scope of the pros and cons of the new approach. As always, I’d love to hear your thoughts, so drop a comment below!

Advertisements

12 thoughts on “Partial Class State Machine

  1. I was finally able to find some time to go and rip out the old state system and put in the new one in the game I am making- it took all of 30 minutes, if that. Now to make a brand new state. So far I am liking it. 🙂

    Liked by 1 person

    1. A state is an object with references to methods as its data. You can pass a reference to any method in its constructor – this could be anything including an instance method on a different object which could even be private, or it could be a static method on a class.

      I provided convenience factory methods that create states and auto pass a reference to a static method of its own called “DoNothing” for use in the event that you don’t care what happens at a particular moment of a state transition. For example, maybe you need something to happen on entering a state, but don’t need to revert anything when exiting the same state.

      You can see the “Do Nothing” method inside of the State class – it has an empty body so it literally doesn’t do anything. It is also a static method, which means no instances of an object need to exist in order to reference it.

      Like

      1. I was just confused about passing the DoNothing method as an Action in the constructors but I looked up the documentation for Action on msdn and it makes sense now. Very cool, I would have used delegates but this cleans things up much better.

        Liked by 1 person

  2. Hm, I don’t quite get how this creates actual statefulness. The Enter and Exit define stuff that happens when you enter and exit the state, but what about in between? How do we enable or constrain what you can do WHILE a state is active?

    For instance, if I want to enable the player to control some actor in one state, and deactivate controls altogether in another, how would you do that? You mention that you cannot have methods with the same names in the partial classes, so how do you create different functionality for Update() (where the controls are usually handled) in different states?

    Sorry if I’m misunderstanding altogether, I still only barely understand state machines as a concept.

    Also, as far as I can tell, this approach seems to require some additional boilerplate code to be written, compared to the one used in Tactics RPG: You need to register all possible states manually, rather than having them simply ‘exist’. All states need a string name, but isn’t actually required by contract or such in any interface. Not the end of the world or anything, but string matching, even when they’re consts, does pet peeve me out. On the other hand, you do get rid of the need to have both a superstate and a controller, so that’s one less class.

    Like

    1. Great questions, here goes…

      In my own personal experience, when using state machines with Unity I primarily only use “enter” and “exit” methods (“update” can be used directly from any MonoBehaviour or coroutine as needed), and I use those as opportunities to modify traits of other entities and not the state itself. For example, I might have a state for a boss that determines what moves it will use, or a state for a menu that determines what buttons to display. When those states have their “enter” method invoked, then they will update the target entity accordingly. If you need the state itself to store information you can still do this by creating a subclass of “State” and add whatever fields you wish. But here again, I almost always would have only added fields to store the values I would want to apply on something else anyway. By injecting the enter method, all of the fields to change can be the fields on the entity itself – no need to duplicate them in a separate state object. Whatever values you assign in the implemented method are “captured” without even needing extra fields.

      Imagine you have a Game controller, which holds a state machine for Play, Pause, etc. When I change states to the play state, I might use the “enter” method to find a “player input” component and enable it. Likewise, when we “exit” the state we might disable the “player input” component so that it wont function in any other game state such as pause or game-over, etc. The player input component would have handled its own update loop while the component was enabled, so there was no need for the state machine to manage it.

      Regarding the additional code – yes, you do need to register the states, but this allows the states not to need to be a monobehaviour subclass. This feature by itself is appealing for a variety of reasons, like less overhead, portability, the ability to share and reuse states, etc.

      Regarding the string for each state, you can think of this as a unique id. It is required, because the string is the key which you pass to the state machine to change states. It allows you to provide your own identifiers for any state, which could allow you to have multiple states in a state machine that share the same class. Also keep in mind that we are not “matching” strings in the sense of slow string comparison checks. The dictionary creates a hash of the string and looks up values using that value. This is significantly more performant than GetComponent as well. Furthermore, if you do create const values for your keys then you also have compile time checking, code completion hints, etc – all the features you would hope for.

      If I missed anything or you need additional clarification, just ask.

      Like

      1. Ah, thanks, that clarifies a lot. I might have picked a bad example though, being quite simple & binary. Turning the component off/on works in that example, but I wonder about a more complex case.

        Namely, I’m trying to imagine the example in the game programming patterns book with the partial class state machine:
        http://gameprogrammingpatterns.com/state.html#the-state-pattern
        His implementation of the state machine seems to basically be the same as the one you use Tactics RPG (I guess it’s the standard way?): State as seperate classes with a superclass and an owner. Here, controls are different in complex ways for each state, which is handled inside the state themselves. In Unity, one would have this code in a seperate Update() for each state. Is this still possible to do with the partial class state machine? Or would you say that it’s just as practical to do this by modifying fields and the like during “enter”?

        Like

      2. Yep, both the state machine in that article and the one used in my Tactics RPG are a pretty standard implementation of a State Machine. However, those patterns were designed for C++ and now we have some nice new features with C# so I re-imagined the approach using modern techniques. It is definitely possible to do separate updates per state using this pattern. It might look something like the following:

        1. Add an additional “Action” field to the “State” class called “Update”.
        2. Optionally add additional convenience factory methods which allow you to pass an update method
        3. Add an “Update” method to the “StateMachine” class. This method should then call “Update” on its current state (assuming it has one, and assuming the state has an update method)
        4. Whatever it is that requires the StateMachine with an Update method, needs to invoke it. For example, if you have an Enemy script which is a MonoBehavior, then you can use the Update method from there to call StateMachine.Update()

        Now you can implement it – suppose you had a JumpState, then you might add a JumpStateUpdate method which you pass to the constructor.

        Like

  3. Cool, thanks, that makes sense. And I would figure you could use the same procedure for any other in-built Unity function (though I suppose the cases where you’d need to do something for instance in Awake() that you could not do in Enter() or the “base” class Awake() are few and far between).

    I honestly still have thoughts, quibbles and questions but as this point, I really just need to try it out for myself and experiment with it.

    Thanks for the answers and thanks for a great blog! It’s benefiting not just my Unity programming, but my skills and mindset as a programmer in general. Keep it up!

    Liked by 1 person

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s