User Interaction States For UnityHow to effectively manage user interaction in a simple, modularized fashion. Unity Style.
As humans, we like to implement solutions which are familiar to us. We get caught up doing things the way we know how to do them, rather than the “best” way to do them. It’s easy to get caught up in thinking like this and as a result we end up using outdated technologies and implement features in ways that our modern contemporaries don’t understand, or are simply less effective or efficient. My purpose with this and future papers will be to expose readers to a broad spectrum of solutions that will hopefully help them in their own coding. Today I’ll be covering User Interaction States, a great way to modularize and simplify the handling of user input into your application.
User Interaction, or player input, can range in complexity from very simple inputs handling such as seen in FlappyBirds, or as complex as something like Call of Duty. Aside from the very simplest of systems, it is extremely important to have a system setup which can help manage user input so that it doesn’t become a mess of if/and statements with dozens of potential states to check for. In my previous User Interaction States paper I addressed a generalized system. In this paper I’m going to add onto that some Unity specific solutions. As such, this is more of an extension of that paper than a full paper in its own right. With that in mind, I suggest you go read that paper first since I will be assuming you have done so and will not retread ground covered there.
Once Upon a Time...
It was a thunderous, stormy Tuesday evening. Previously sunny, the weather had turned cold and unforgiving upon my starting a new project using… UNITY. It was a small contract, but the desired platform was WebGL, and while FlatRedBall is a superb engine, and the one I use most often for my own projects, it does not support WebGL. While setting up the project basics, I was about to set up my UserInteractionStates in the usual manner when Frankie, my genius dog, interrupted. “Why not use Unity’s inspector and metafile data to setup the appropriate references required by the UserInteractionStates, rather than passing that information into the class programmatically?”
Well… why not? Well played dog, well played.
Unity lets you expose public fields in the inspector, which you can then drag and drop different objects into, allowing the class (or script in unity parlance) to access a reference to that object. For our purposes, that means we can provide the references directly that way instead of requiring that they be passed in via the UserInteractionState’s instructor. Unity GameObjects, which our User Interaction State MonoBehaviours will be attached to, also have convenient ability to be enabled or disabled, and scripts have OnEnable and OnDisable methods. So instead of creating our own IUserInteractionState interface, we will simply use these.
Now that we’ve gone over the theory, it is useful to step through a practical implementation. First lets setup our scene. The first step is to setup the empty GameObjects we will need.
Next, let’s create the scene controller. This script will need a reference to each of its User Interaction State game objects, as well as a public function which can be called to load a UserInteractionState. Because we are not crazy people, we will use a custom Enum as an argument instead of strings.
Note that the UIS references up top for Default, Menu, and Building, will be set from within the inspector instead of having the code grab it at runtime. Let’s create those UIS scripts now so that we can add them too. Each of these scripts will need, at minimum, an Update, OnEnable, and OnDisable methods.
For our particular UIS_Default script, we are also going to want references to the SceneController so we can trigger the loading of a new User Interaction State, a reference to a Player so we can move it, and finally a reference to the Menu button so we can detect when it is clicked on.
Before we explore this class any further, let’s add these scripts to their GameObjects in the inspector and setup the appropriate references. I’ve already setup the UIS_Menu and UIS_Building scripts, but we are just using them as placeholder examples and will not be exploring their contents. I’ve also setup a Player with a PlayerController script so we can reference it.
Now that we have our references setup, we can start adding functionality into the UIS_Default script. The first thing we want to do is subscribe to events in our OnEnable method, and unsubscribe from them in the OnDisable method. This keeps the event method from firing when the User Interaction State is not loaded. There are other ways of doing this, but this is a nice and clean method.
Now we need to setup the code which responds to a click. In this case, we want the SceneController to load the UIS_Menu User Interaction State when the menu button is clicked on.
Finally, we need to setup the LoadUserInteractionState code in the SceneController. We need to both disable any current User Interaction State, and also set the new one to active. We will keep a reference to which state is loaded so that we can easily disable it later.
Now, whenever the Default User Interaction State (UIS_Default) is loaded and you click on the MainMenu button, the SceneController will load the Menu User Interaction State (UIS_Menu). This state will of course subscribe to input relevant to the Main Menu, and not have any code related to moving the player or other in game activities.
Remember, by segregating your User Interaction detection code into separate class implementations you can keep your input code from getting real messy with if/and/switch statements that try to determine when certain actions are applicable and when they should be detected. And by unsubscribing to input when detecting that input is unnecessary, we can prevent strange behavior when the player manages to interact with the UI and games in ways that we don’t initially plan for – such as clicking on a button while its animating off screen.
As with anything in coding, there is often no best solution. It is important to keep a large variety of coding tools in our toolbox so that we can pick the right one for the problem at hand. User Interaction States turned out to be perfect for King Randall’s Party and FlatRedBall, and were easily adapted to use in Unity on my other projects. Hopefully they will be useful to you as well.
Share this Post