“Press E to interact,” “Press F to talk,” “Hold right trigger to use.” These prompts are likely to sound familiar to anyone who has played video games. Having some unified way of turning button presses into actions that are dependent on where the player is and what the player is looking at is a common user experience problem that many video games have had to solve over the years. It is typically sectioned off into a so-called “interaction system” of the game that provides the developers with a consistent way of enabling objects in the game world to be used by the player, picked up, or whatever else the game needs the player to be able to do.
In Land of Lights, the player needs to be able to press an interact key when standing near or looking at an object, and have that object do something. For example, the player needs to be able to activate a monument by walking up to it and pressing E. The player also needs to be able to pick up and carry various gameplay objects, such as rocks to use for puzzles and light crystals to transport units of light around the map.
In addition to Casta’s interactions with the game world, there are several actions that Guppy needs to take on behalf of Casta, namely the ability to give and take light from plants, crystals, and other puzzle objects. There are also instances where Guppy needs to be able to interact with something which Casta cannot, without necessarily giving or taking light.
One of the simplest ways to implement such a system in our game engine of choice, Unreal Engine 5.2, would be to create base components for interaction, pickups and light containers, and then extending them with child component classes that handle activating a monument, or taking light from Guppy and growing a plant, or whatever is needed for that specific object.
However, due to technical limitations in Unreal, this solution would lock us into always having to use components for these interactions. We could never have a one-off object that handles interaction directly. We would also have to implement each interaction type as a separate component, and add each component to every object separately, which wastes time, adds unnecessary complexity, and creates more opportunities for mistakes to happen when setting up each object in the game world.
For the interaction system that we ended up implementing in Land of Lights, we made extensive use of one of Unreal Engine’s interfaces. Interfaces let us define a set of functions that we can then implement on any other object type in the engine, allowing us to implement interaction on actor objects or components, using either of the two languages supported by Unreal: C++ or Blueprint scripting.
This solution turned out to be extensible: we were able to, much later in development, add another interaction interface for things in the game world that Casta should be able to command Guppy to “focus on” or go and stand by until Casta tells him to come back.
We also, quite recently, found another great use for interfaces. We have several types of objects that hold light, and while there was a common interface for Guppy to give and take light to and from these objects, there was no consistent way to get the amount of light contained in any of these objects. Using Unreal’s interfaces, we were able to make a unified method for getting the stored light value from any object in the game world.
Having a well thought-out interaction system in a 3D video game is veryimportant to a good user experience design. Land of Lights is no exception, and designingthe entire system before building it out has allowed us to create a highly extensible system that effectively handles all interactions with the game world.
Comments
One response to “Creating a Robust Interaction System”
[…] analysis about how our team developed the interaction system can be found in a previous blog post, “Creating A Robust Interaction System,” if you would like to know more about the finer details.) The interaction system allows the player […]