Unity Dev: Player Movement (New Input System)

Alex Somerville
5 min readMar 19, 2021

--

You got your cube moving around in my last article, but you’ve heard about Unity’s New Input System and you’re inexplicably drawn to things that have “new” in the name. In this article, we’ll walk through installation of the New Input System, and overhaul our previous movement system using an event driven system. This will also allow us to easily provide support for multiple input types.

Source: https://unsplash.com/photos/tk2_RBZq7RA

Install

  1. Window > Package Manager
  2. Ensure you’re looking at “Packages: Unity Registry” and run a search for “Input System”.
  3. Select “Input System” from the list that’s returned and use the Install button in the bottom right of the Package Manager window.

Installing this package will disable the original Input Manager.

Setup

  1. Edit > Project Settings > Input System Package
  2. Click “Create settings asset”
  3. You can leave the default settings for now.

Setup InputActions object

If you try to run your game now, you’re going to get hit by an error that looks like this:

This is because we disabled the old Input Manager, so we need to take some steps to make use of the newly installed Input System instead.

  1. Click on your “Player” object in the Hierarchy window.
  2. In the Inspector window, Add Component > Player Input.
  3. You’ll be prompted to save your new .inputactions file. I’ve created a folder in Assets called “InputActions” and named the file “Controls”
  4. Double-click the Controls item in your Project window

Because we’re focusing on movement, let’s delete the “UI” action map, as well as the “Look” and “Fire” actions. Additionally, selecting the “Auto-Save” checkbox can save you a headache in the future.

Click on the Action called “Move” and change the Control Type to “Vector 3”.

Click on your Controls object in the Projects window, turn on “Generate C# Class” and click “Apply”.

Click on your Player object to view it in the Inspector. Drag PlayerActions from your Assets into the “Actions” value in the Player Input component and change the “Behaviour” to “Invoke Unity Events”.

Code Refactor

Go ahead and open up your Player script in your IDE and we’ll make a couple changes here.

First, we want to delete the following lines in void Update():

float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical");

Next, we’ll remake these as a single so that we can feed it values whenever input is triggered.

private Vector3 _direction;

Then we’ll make a small revision to the class definition:

public class Player : MonoBehaviour, Controls.IPlayerActions

We add , Controls.IPlayerActions to the class definition so that it can reference the C# class we made out of our Input Action Asset earlier. Depending on your IDE, you may see this throwing an error. “Controls” will be different depending on what you called your Input Actions asset.

Clicking to light bulb here will give you the option to “Implement Missing Members” which will auto-generate a void called OnMove that is triggered whenever one of our defined Actions is triggered by the inputs we’re watching for as defined in the Input Actions.

Back to Unity

We’ll need to jump back to Unity for a moment now that we’ve got our void OnMove() defined.

In the Player object, find your Player Input component and expand Events > Player. Hit the “+” in the “Move (CallbackContext)” box. Drag your Player object from the Hierarchy window to the empty Object space and then No Function > Player > OnMove.

Back to Code

Before we move on, it’s important to understand that we’re no longer actively checking if the player is providing input inside of our void Update()

The new Input System supports event driven interactions so we’re only running movement related code when the user is actively attempting to move.

Back in our code we now have our void OnMove() defined and we can start working with it. First up is getting some sort of value we can use back from our context object.

public void OnMove(InputAction.CallbackContext context)
{
Debug.Log(context.ReadValue<Vector2>());
}

The above is going to fetch us a Vector2 to represent our horizontal and vertical axes. The Debug.Log I’m using would read out in a couple different ways. For instance, if we’re pressing the the D key, we’ll see (1,0) whereas the S key would read (0,-1)

Now that we know we’re getting values back from our inputs, we can start feeding that Vector2 value into our _direction Vector3, like so.

public void OnMove(InputAction.CallbackContext context)
{
_direction = context.ReadValue<Vector2>();
}

One final step. We’re going to revise the code we have in our void Update()

void Update()
{
transform.Translate(_direction * (_speed * Time.deltaTime));
}

Because we’re storing our _direction as a Vector3, we can now control the movement with a single line of code by multiplying (_speed * Time.deltaTime) by our _direction

Hop into Unity and run your game. You should be able to use the WASD keys just like before, but if you hook up a gamepad, XR controller, or a Joystick, you’ll be able to use those instead!

--

--

Alex Somerville
Alex Somerville

Written by Alex Somerville

On a quest to become a game developer. Still sometimes providing unsolicited advice about how to function in society.

Responses (2)