The Input System
Actions, maps, and device support
Unity has two input systems, and most tutorials you find use the old one. Knowing which you are looking at saves a lot of confusion, because their code does not mix.
Old vs new
| Input Manager (old) | Input System (new) | Note |
|---|---|---|
Input.GetKey(KeyCode.W) | moveAction.ReadValue<Vector2>() | New reads a value, not a key. |
Input.GetAxis("Horizontal") | Action with a 2D vector binding | Bindings live in an asset. |
Built in, nothing to install | Package Manager install | Extra setup, far more capable. |
Rebinding is manual work | Rebinding is built in | A real accessibility win. |
Polling only | Polling or callbacks | Events avoid missed presses. |
Input.GetKey calls start throwing InvalidOperationException. If you need both during a migration, set Active Input Handling to Both in Player Settings.The mental model
The new system separates what the player wants to do from which button they pressed.
- Action — an intent, like "Jump" or "Move".
- Binding — a control that triggers it. One action can have many.
- Action Map — a group of actions for one context, like Gameplay or Menu.
- Action Asset — the file holding all of it.
Your code asks "is the player moving?" and never asks "is W held?". Add a gamepad stick as a second binding and the same code supports controllers with no changes.
Setting it up
- 1 Install the package
Window → Package Manager → Input System. Unity restarts the editor afterwards.
- 2 Create an Input Actions asset
Right-click in the Project window: Create → Input Actions. Double-click to open the editor.
- 3 Add a map and some actions
A
Gameplaymap withMove(Value, Vector2) andJump(Button) covers most games. - 4 Bind controls
Give
Movea 2D Vector composite for WASD plus the gamepad left stick. GiveJumpSpace plus the south button. - 5 Tick Generate C# Class
In the asset's Inspector. That produces a typed wrapper you can use directly.
Reading input
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerInputHandler : MonoBehaviour
{
private PlayerControls controls; // the generated class
private Vector2 moveInput;
private void Awake()
{
controls = new PlayerControls();
// Events: never miss a press, even between frames
controls.Gameplay.Jump.performed += OnJump;
}
private void OnEnable() => controls.Gameplay.Enable();
private void OnDisable() => controls.Gameplay.Disable();
private void OnDestroy()
{
controls.Gameplay.Jump.performed -= OnJump;
controls.Dispose();
}
private void Update()
{
// Polling: right for continuous values like movement
moveInput = controls.Gameplay.Move.ReadValue<Vector2>();
}
private void OnJump(InputAction.CallbackContext context)
{
jumpQueued = true;
}
}FixedUpdate trap from the lifecycle topic.Enable(). A brand-new action asset produces no input at all until its map is enabled — the most common "nothing happens" moment with the new system.Switching contexts
Action maps make pausing trivial. Disable Gameplay, enable UI, and movement keys stop driving the player while menu navigation starts working — no isPaused checks scattered through your code.
public void Pause()
{
controls.Gameplay.Disable();
controls.UI.Enable();
Time.timeScale = 0f;
}
public void Resume()
{
controls.UI.Disable();
controls.Gameplay.Enable();
Time.timeScale = 1f;
}Rebinding
Interactive rebinding in a few lines
Letting players remap controls is a real accessibility feature, and the new system makes it genuinely simple.
public void StartRebind(InputAction action, int bindingIndex)
{
action.Disable(); // required while rebinding
action.PerformInteractiveRebinding(bindingIndex)
.WithControlsExcluding("Mouse")
.OnMatchWaitForAnother(0.1f)
.OnComplete(op =>
{
op.Dispose();
action.Enable();
SaveBindings(action);
})
.Start();
}
private void SaveBindings(InputAction action)
{
PlayerPrefs.SetString("bindings", action.actionMap.asset.SaveBindingOverridesAsJson());
}Touch
Touch is just another device. An on-screen stick can bind to the same Move action as WASD, so your movement code never learns it is running on a phone.
What to take away
- Check which input system a tutorial uses before following it.
- Actions describe intent; bindings describe buttons.
- Call
Enable()or you get no input at all. - Poll continuous values, use callbacks for discrete presses.
- Action maps make pause and menu contexts clean.
- Rebinding is built in — use it.