How to use Unity’s new Input System to simplify and expand your game’s controls
This guide will show you how to stop using if-else statements for player controls with Unity’s new modern approach
If you are a Unity game developer, how many times have you started your game project by writing the Player GameObject’s controls? Nothing gets motivation rising like seeing a Capsule or Cube move when you press the keyboard’s arrow keys. A few if-else statements lead to some working movement.
How often have you seen or even written code like this for your player movement?
if(Input.GetKeyDown(Keycode.A)){
// move left
}else if(Input.GetKeyDown(Keycode.D)){
// move right
}else if(Input.GetKeyDown(Keycode.W)){
// move up
}else if(Input.GetKeyDown(Keycode.S)){
// move down
}
Don’t get me wrong, this works fine for some games. But what happens when you want to add projectile fire? Then you want to add some melee weapon attacks, what then? Your player has to drive a car through a course — how do you set up the new controls so they don’t interfere with the old? Wait, you also need controller support?!
As you can see, programming inputs gets a little messy once you get past the basics.
Unity has listened to developers and their complaints about a lack of versatility and ease of deployment. Their answer is through their new Input System which is now in version 1.0.1 as of Unity 2019.4. I have personally switched over to the new Input System and it's fantastic. It simplifies the code required to get working input, into something much easier to read.
Some of the great things about Unity’s new Input System include:
- Unity Events and delegates for handling what happens on the input
- Control scheme support to segment out different modes of control
- Simplified trigger selection, whether it’s keyboard, mouse, or gamepad
Without further ado, let’s get into how to get started using the new input system!
Installation
1. Install the Input System from Unity’s Package Manager. From the top menu, Window > Package Manager. Then choose Package: Unity Registry from the top left of the Package Manager view. You should now see the option to Install (or Update if it’s already installed)

2. Right click in your Project view, and choose Create > Input Actions. Name it whatever you’d like (I’ve named mine “PlayerControls” in this example). Note: This name will be referenced again in your code so name it appropriately.
3. Click on your Input Action Asset. You should see information about the asset show up in the Inspector. Make sure you click the checkbox next to “Generate C# Class” and click “Apply”. This will create the InputAction class you will use in your code.

4. Finally, double click the Input Actions object you’ve just made, and it will open the Input Actions view in Unity, where you can begin creating your implementation of the Input System.
Set up your Actions and Triggers

- You will be shown a view like the above to begin editing your Actions. Except yours will be empty, time to fill them!
- Let’s start with Action Maps. Action maps are the groupings of actions that can be taken in your game. For example Player controls, UI controls, and other modes in your game. In the above example I just made one called “Gameplay” for simplicity, but you can make as many as you’d like.
- Actions Are the actual action events. You will want to name them so they are relevant to your game. For example, “Menu Confirmation”, “Menu Cancel”, “Move”, “Fire Projectile”, etc will each have their own unique bindings for player controls. The key here is that you can add multiple bindings per action. This allows some flexibility whether players are using Keyboard, Gamepad, or other input means.
- Properties are, as you’d expect, the properties like the bindings that can trigger your action. They are ways to capture the event, e.g., Z Key on Keyboard, A button on Gamepad, and Left stick on Gamepad. Note that for movement you can map any 4 buttons for a 2D Vector, e.g. the Arrow Keys on the Keyboard.
- Create your desired actions and bindings until you are satisfied and ready to code them in your game.
- Note: When you are done changing your Actoins, Bindings, or anything else in this view, make sure you click “Save Asset” at the top. If you do not, you won’t see your changes reflected in the code!
Writing Player Controls
Now, it’s time to start writing code for your Input Action Asset. Make sure you’ve generated a C# script for your Input Action asset and you have clicked “Save Asset” from the previous step.
1. Create your Player.cs script that will hold the code for player controls.
2. Open your script and start writing your code to reference and access the actions you created in the previous example. Make sure you import UnityEngine.InputSystem. First you need to make sure the controls are enabled and disabled for the script. You can do this as following:
PlayerControls controls;void OnEnable() {
controls.Gameplay.Enable();
}void OnDisable() {
controls.Gameplay.Disable();
}
3. Note the “PlayerControls” and “Gameplay” are both fields that I named in the last section. Yours most likely are named differently. Use your InputAction asset name and your Actions name, respectively
4. In Awake() you will want to instantiate your InputSystem and attach methods to the actions you made in the previous section. Here is an example of a “MeleeAttack” action being performed:
void Awake(){
controls = new PlayerControls();
controls.Gameplay.MeleeAttack.performed += Melee;
}void Melee(InputAction.CallbackContext ctx){
// Code for performing a melee attack
}
Notice how Melee has a parameter of type InputAction.CallbackContext. This is a context variable passed by the Unity Input System so you can read an use explicit values in your function. Here is another example that is both an anonymous function and uses the context:
Vector2 vel;void Awake(){
controls = new PlayerControls(); controls.Gameplay.Move.performed += ctx => {
vel = ctx.ReadValue<Vector2>();
}; controls.Gameplay.Move.canceled += ctx => {
vel = Vector2.zero;
};
}void Movement(){
// code using "vel" as player's velocity
}void Update(){
Movement();
}
The above example uses ctx.ReadValue<Vector2>() to get the exact value of the joystick or arrow keys and sets it to a global variable for velocity. When the joystick is not being actuated (in the “canceled” instance) the value of vel is set to the zero vector, i.e. Vector2.zero. You can use this kind of action for buttons that you want to only have effect when they are held down.
Hopefully these steps have taught you the basics of how to use Unity’s new Input System! If you need more in-depth examples please refer to the UnityDocs on the subject.
Alternate method — On the Update Loop
If you are still interested in performing Input actions on the Update loop, there’s still a way to do this. It has become easier and dare I say more flexible than ever. You don’t need to create an InputAction asset or create Action Maps, Actions and Bindings if you use this method.
In FixedUpdate() you can listen for different values from the Input System, like in this example:
void FixedUpdate(){
var keyboard = Keyboard.current;
if(keyboard == null){ return; }
if(keyboard.zKey.wasPressedThisFrame){
// perform action here
}
}
Being able to check if a key was pressed on a device like keyboard, mouse, or gamepad is a huge improvement over the old system. Even if you decide to use the Update loop to handle input, you can rest knowing there’s additional functionality to help you out!
Conclusion
With this, you are well on your way to using the new Input System to make some fantastic games. I am sure that we will see even more features added to the new system for Unity, as it is in its infancy.
Interested in learning more tips and tricks related to Unity IDE? Need to improve your C# knowledge so you can code your dream game? If so, check out some of my other articles on Unity tips and tricks.