Move it!…again!
Using Unity’s new input system for movement
Today we’re going to look at moving our player…wait. Haven’t I already written this article? That’s right I have already presented an article on moving our player, but that article used the default Input Manager that Unity provides out of the box. Today we are going to look at how to do it all over again using Unity’s new Input System!
Install the new system
First, we need to install the new Input System
- Open the Unity Package Manager
- Searching for “Input System”
- Click the “Install” button.
It is important to note that installing the new Input System will disable the default Input Manager. Unity may display a prompt warning of this and asking to restart to enable the new system.
Now we need to initialize the new Input System.
- Open the Project Settings
- Select “Input System Package”
- Click the “Create settings asset” button
- Accept the Defaults
This will place a new asset file in your project hierarchy.
Set up the PlayerInput component
The next thing we need to do with the new Input System is to tell the system what actions are mapped to which controls for each type of controller we are supporting. To do this we need to attach a PlayerInput component to our player.
Once we have a PlayerInput component attached to our Player object we need to create an Input Actions file. This file holds the mappings and settings for our controls.
If we select our newly created InputActions asset file in the Project panel, we can click the Edit Asset button to open a settings window for the Input Actions.
By default, Unity creates a few sets of bindings for us. If we click on “Player” under “Action Maps” we can see that we have been provided with Actions for Moving, Looking around, and Firing by default. We have also been provided with an Action Map for UI interactions. For now, since we know we will need to move the character and we plan to add the ability to fire in a future article, let’s keep those settings and delete the Look Actions and the UI Action Map. 1. Right-click on “Look” and Select Delete 2. Right Click on UI and Select Delete 3. Click Save Asset 4. (Optional but recommended) check the Auto-save checkbox
Once we have our Maps set we need to tick the “Generate C# Class” option on the Input Actions Asset object and hit apply to generate a class file with our settings.
Now we want to tell our Player Input component which Input Action Asset to look for.
- Select our Player object
- Drag our Input Action Asset into the Actions field on the Player Input component
Lastly, we are going to select “Invoke Unity Events” from the Behavior drop-down on our Player Input component. There are a few advantages that we get using Unity Events over the other options. Among them, the additional properties and methods on the InputAction.CallbackContext object are useful over the InputValue object returned by the Send Messages and Broadcast Message options and the visual assignment of handlers in the Unity Editor is also helpful.
Modifying our code
Whew! That was a lot of setup! Let’s modify our existing movement code and see if we can get the new Input System to give us the same result as the old one. First, let’s extend our Player class to use the IPlayerActions interface from our Controls class (or whatever you called the class). To do so we need to change our class definition to include the Interface.
We can have our IDE implement the functions that are necessary for us to receive our Unity Events from the new Input System that we setup. Right-click on the Interface declaration and choose to implement missing members. I am using JetBrains Rider as my IDE in the example below instead of Visual Studio but Visual Studio has a similar feature.
Doing this will create methods for the OnMove and OnFire methods from our interface (We’ll use the OnFire method in a future article). It is possible to manually add these methods but using the IDE tools helps to ensure that the method signatures are correct.
Let’s add a new variable to hold the value of the input that we will receive back from the Input System. our Move keybinds are set up to return a composite Vector3 so let’s make our variable of the same type. This variable is going to hold information about both the horizontal and vertical axis’ and so we only need one variable as opposed to the 2 we were previously using.
And now let’s populate the variable whenever we get notified from our input system that movement has been triggered.
Ok, we have our input from the new system. Let’s plug it into our previous movement code and clean up our Update method! First, let’s update the old movement code
to use the new variable
and remove the variables we no longer need
Our last step is going to be hooking up our OnMove method from our player class to the Move function of the Player Input component. Back in Unity, we need to open our Player object in the inspector and locate the Player Input component.
- On the Player Input component expand the “Events” node
- Expand the “Player” Node
- Hit “+” in the “Move (CallbackContext)” section
- Drag the Player object from the Hierarchy window to the input that says “None (Object)”
- Open the drop-down that says “No Function”
- Select Player
- Select OnMove
Next Time!
That’s it! Now that we have connected the callback method with the event that is fired we should be able to run our game and move the player just as before. Additionally, if we connect a controller to our setup we should now also be able to move the player with the joystick on the controller! Tomorrow, we will look at hooking up the OnFire method so that we can fire our lasers with the new system as well! If you enjoyed this article, or want to come along with me as I progress on my journey, follow me at gamedevchris.medium.com.