March 6, 2020
Player input is what separates video games from television: it gives viewers the ability to interact with the fictional world they are watching. But player input devices have been evolving for as long as video games have been around. From the simple dials of Pong, to the revolutionary handheld of the SNES, to the debauchery that was the Xbox Kinect, people have reimagined the way they interact with the digital world time and again.
And now with the advent of virtual reality gear, input hardware shows no signs of slowing down any time soon.
The diversity of hardware inputs creates a world of new possibilities, but also creates a dilemma to match: as a game developer, how can you keep your game updated to handle input in so many different ways? If you try to handle only a select few inputs, you may be limiting your game to one platform. But on the other hand, if you try to handle every type of input (gamepad, keyboard, joystick, Ouya) you may find yourself stuck in a cycle of having to update input handling every time the platform changes.
Fortunately, Unreal Engine 4 provides an elegant, cross-platform solution to this problem. The Engine's input framework is made up of three parts: mappings and bindings, held together by input identifiers.
At the heart of the input framework is the humble input identifier, a simple string that describes the input. For example, a jump input might have the obvious identifier
Jump. In other words, an input identifier simply says what an input is.
This identifier helps the Engine relate mappings and bindings to one another.
Input mapping involves connecting raw hardware inputs to input identifiers. In other words, an input mapping defines which hardware inputs to react to. Unreal Engine 4 accommodates a wide variety of hardware inputs, including keyboards, console controllers, virtual reality inputs, and even virtual joysticks (like those used in mobile games). You can map any number of hardware inputs to a single identifier.
For example, we can map the keys
Up to the identifier
Jump. Input mapping can be done at build time through ProjectSettings or manipulation of config files, and it can be done at runtime through C++ or Blueprints.
Input binding is the process of connecting input identifiers to game-specific events. In other words, an input binding defines what happens when input is received. Those events can have arbitrary names, and any number of events can bind to a single delegate. Input binding can be done at runtime through C++ or Blueprints.
Continuing our example, we can bind a
Jump() function in our Character or PlayerController to our
Tying everything together, the end result for our
Jump example looks something like this:
Spacebar, ControllerX, Up === (Mapping) ===> (Identifier) Jump <=== (Binding) === Jump()