Using Command pattern to handle input in Unity and C# (Part II)

by on Nov.26, 2015, under Unity3D

<—— Using Command pattern to handle input in Unity and C# Part I

In my previous post, I was just introducing how to apply the Command design pattern to handle our game’s input (in Unity and C#). At the end of part I we came up with a simple solution to handle it, but we were still missing a “way” to adapt our code to different game scenarios (menus, in-game, … ). For example in the code I wrote there, we were assigning the A button to the fire action. But what if we are in the main menu and we just want to assign this button to accept instead of Fire? In this second part, I will try to adapt the code we developed before in order to support different game scenarios.

Let’s then first modify the base class in order to “store” the method we are supposed to call. Yes, you probably wonder by now that I am referring to C# delegates / actions. Our Command base class now will include a new Action var:

    public abstract class Command
    {
        protected Action command;

        public Command(Action _command)
        {
            command = _command;
        }

        public abstract void Execute();
    }

Once we have modified our base class, we will have to create only 1 instance or unique type of controller (or create a few different implementations, but for this example with 1 is enough). So, lets include some logic in our InputAction class to call the Action or Delegate its supposed to:

    public class InputAction : CommandBase
    {
        public InputAction(Action _command) : base(_command)
        {
        }

        public override void Execute()
        {            
            if (command != null)
            {
                command();
            }
            else
            {
                throw new NoMethodToExecute();
            }
        }
    }

As you can see in the code above, I am checking that the command variable (C# Action) is not null. This is a safety check that can be avoided to save improve performance, but of course we will need to be 100% sure it is always with a value (to avoid our game just crashing or having strange behaviours). One solution here could be to use the NullObject pattern (but this will come in some separate post). Also you can see that I am throwing a NoMethodToExecute exception. This is just a custom exception I made to handle when our command is null (source code in the github link I posted below).  So now we can create a lot of different InputActions just changing the method those ones will be calling when they will have to be executed. Let’s now modify our InputManger class to support this new functionality:

public class InputManager
{
	private Dictionary commandList;

	public InputManager()
	{            
		commandList = new Dictionary<string , InputAction>(();
	}

	public void AddControl(string _cmdName, Action _cmd)
	{
		if (commandList.ContainsKey(_cmdName))
		{
			commandList[_cmdName] = new InputAction(_cmd);
		}
		else
		{
			commandList.Add(_cmdName, new InputAction(_cmd));
		}
	}

	public void ResetControls()
	{
		commandList.Clear();
	}


	public void ExectueCmd(string _cmdName)
	{
		if (commandList.ContainsKey(_cmdName))
		{
			commandList[_cmdName].Execute();
		}
		else
		{
			throw new NoCommandToExecute();
		}

	}
}

As you can see above I am using a Dictionary (with a string as a key) to store all our events. This is not the most efficient way to store them, but for this example will do :). Basically I just create a new InputAction for all the Input we would like to handle. For example, following the 2 events we worked with in Part I (Jump and Fire) we will add them into our newly created InputManager as follows:

commandList.Add("jump", new InputAction( OnJump ));
commandList.Add("fire", new InputAction( OnFire ));

In the code above, “OnJump” and “OnFire” are the functions or methods that will handle the jump and fire logic (usually in some kind of player control).

And that’s all. With this simple implementation we will handle our game’s input using the command pattern. I will be writing part III sometime in the future as we will need an “Undo” operation in Dimension Drive. This type of operation is easily implemented with the Command pattern as well. It is also really good to save all the commands your game is handling so you can “easily” implement a “replay” or ghost mode. But let’s not spoil all the fun as probably that will have a big impact in Dimension Drive (the game I am working on right now). If you want to access the source code of this post so far (including a Unity example on how to use it), please see in my github public repository here.


Leave a Reply