Recently at Pentatonic Games, we’ve been hard at work on a new, custom input system for our upcoming title, Gloom Box [working title]. While there are many input wrappers for sale on the Unity Asset Store, we decided to create our own for a number of reasons: to gain experience working with and around Unity’s built-in Input class, to have total control over the functionality surrounding input, and to save money.
Let’s start with the basics: Why couldn’t we use Unity’s built-in InputManager exclusively? It’s free, easy to configure, can be used with multiple input methods at once, and requires little or no code.
Primary answer: InputManager has no support for reconfiguring inputs at runtime. Because we’d like our game to be accessible to people of many and varied abilities, it is necessary to present the player with a customizable, remappable input scheme. To do this, being able to set inputs at runtime is a must, and Unity’s InputManager is insufficient.
So, how did we go about creating a robust, yet malleable input system for controller, keyboard, and mouse?
1. We started with a solid controller, keyboard, and mouse state class.
We frequently got confused when working with Unity’s built-in input system, especially when using Input.GetKey() and Input.GetKeyDown(). Not only are these function names ambiguous, but they also work for more than the keyboard. They can detect controller button presses (but not controller axis movement).
To mitigate this confusion, we decided to wrap Unity’s Input class in our own KeyboardState class (for these purposes, the KeyboardState class includes controller, keyboard and mouse state). This allowed us to check input only on the necessary keys, buttons, and axes and to create custom accessor methods for various events on all input devices.
In the KeyboardState class, we keep lists of all controller axes, controller buttons, keyboard keys, and mouse buttons we will be checking for input. For each of these input categories, we also keep lists of the inputs that are pressed, just pressed this frame, and just released this frame. Many of these lists are public and static, meaning they can be accessed from outside of the KeyboardState class; others are private but have accessor methods that allow other classes to check if a single axis/button/key is pressed, just pressed, or just released.
We believe our method terminology, as well as the separation of inputs into disparate lists, clarifies the ambiguity of Unity’s Input significantly.
2. We backed it up with a custom input manager.
This is where we really began our remappable input journey. In our custom InputManager class, we keep strings representing all of the input axes, buttons, and keys our player is currently using. These strings are read from, and written to, a simple text file with lines that look like
for the “jump” input on the controller and
for the “move left” input on the keyboard.
In the custom InputManager class, we created a public, static function to set the mapping of a particular player input to a particular axis, button, or key. We also added a number of helpful dictionaries that allow us to convert from the shorthand we use in our text file to the strings and Keycodes that Unity understands and back again.
3. We created a manager for remapping keys.
The RemapKeys class, as we call it, runs whenever the player is on the options screen that allows them to remap their inputs. RemapKeys presents a simple key change GUI to the player. It creates a new text file, or keymap, where the player’s configured inputs will be saved. When the player changes one of their desired input axes, buttons, or keys, RemapKeys saves over the keymap. The next time the player plays Gloom Box, the new keymap will be read into our custom InputManager and used throughout the game.
This is a brief summary of the methods Pentatonic Games used to create a custom, remappable input scheme and wrapper for Unity. For more information, or for code samples, please feel free to contact us using the “Contact” tab on this page.