Input System
Unity's modern Input System package — flexible remapping, multi-device support, and event-driven actions — replaces the legacy Input.GetKey() polling API.
Imagine...
The old Input System is staff calling every 0.016s to ask “Any customers yet?” (polling). The new Input System installs a doorbell (events) — you only hear when someone presses it. Action Maps are like a dispatch board — the same “Confirm” button means Navigate Accept in a menu and Jump in gameplay. No `if (context == menu)` spaghetti.
The concept in detail
An Input Actions Asset is a
.inputactions file that holds every binding. It is organized into
Action Maps (Gameplay, UI, Vehicle…) → each Map has
Actions (Move, Jump, Fire…) → each Action has
Bindings (keys, sticks, gamepad buttons…).
Event-driven: Subscribe to
action.started, action.performed, action.canceled. Call
context.ReadValue<Vector2>() for values. No Update polling required.
Player Input component: Attach it to a GameObject to wire events automatically. Supports Messages, C# Events, or Unity Events.
Runtime remapping:
action.AddBinding() and
InputActionRebindingExtensions.PerformInteractiveRebinding() let players change
keybinds in a Settings menu.
Diagram: Input System architecture
Input Actions Asset (.inputactions)
Actions: Move, Jump, Fire, Interact...
started / performed / canceled events
PlayerController
OnMove(ctx)
UINavigator
OnNavigate(ctx)
VehicleDriver
OnSteer(ctx)
Hands-on steps
Install the Input System package
Window → Package Manager → Input System → Install. Restart when prompted.
Create an Input Actions Asset
Assets → Create → Input Actions. Add Action Maps, Actions, and Bindings for each key/button.
Generate a C# class
Select the .inputactions file → Inspector → check "Generate C# Class" → Apply → Unity emits a wrapper class.
Subscribe / unsubscribe events
OnEnable: _actions.Gameplay.Jump.performed += OnJump; OnDisable: unsubscribe the same way.
Interactive simulator
Press keys (or the buttons below) and watch events reach the right listener for the active Action Map.
Virtual Input
Event Log
Press a key to see events...
Code example
BasicUse a generated C# class with event subscriptions.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private GameControls _actions; // Generated C# class
private Rigidbody _rb;
private Vector2 _moveInput;
void Awake()
{
_rb = GetComponent<Rigidbody>();
_actions = new GameControls();
}
void OnEnable()
{
_actions.Gameplay.Enable();
_actions.Gameplay.Move.performed += OnMove;
_actions.Gameplay.Move.canceled += OnMove;
_actions.Gameplay.Jump.performed += OnJump;
}
void OnDisable()
{
_actions.Gameplay.Move.performed -= OnMove;
_actions.Gameplay.Move.canceled -= OnMove;
_actions.Gameplay.Jump.performed -= OnJump;
_actions.Gameplay.Disable();
}
void OnMove(InputAction.CallbackContext ctx)
=> _moveInput = ctx.ReadValue<Vector2>();
void OnJump(InputAction.CallbackContext ctx)
=> _rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
void FixedUpdate()
=> _rb.velocity = new Vector3(_moveInput.x * 5f, _rb.velocity.y, _moveInput.y * 5f);
}Code example
AdvancedInteractive rebinding — let players change keybinds at runtime.
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class KeyRebinder : MonoBehaviour
{
[SerializeField] private InputActionReference jumpAction;
[SerializeField] private TextMeshProUGUI bindingLabel;
private InputActionRebindingExtensions.RebindingOperation _rebindOp;
public void StartRebind()
{
jumpAction.action.Disable();
bindingLabel.text = "Press any key...";
_rebindOp = jumpAction.action
.PerformInteractiveRebinding()
.WithControlsExcluding("Mouse")
.OnMatchWaitForAnother(0.1f)
.OnComplete(op => {
op.Dispose();
jumpAction.action.Enable();
bindingLabel.text = InputControlPath.ToHumanReadableString(
jumpAction.action.bindings[0].effectivePath);
// Persist binding overrides
PlayerPrefs.SetString("JumpBinding", jumpAction.action.SaveBindingOverridesAsJson());
})
.Start();
}
}📌 Quick recap
- ▸Enable/Disable ActionMaps by context (Gameplay ↔ UI)
- ▸Subscribe in OnEnable, unsubscribe in OnDisable
- ▸
performed= pressed;canceled= released - ▸Generate a C# class → cleaner API + IntelliSense
⚠️ Common mistakes
❌ Forgetting Enable() on the Action Map
Actions never fire even after subscribe — silent failure
✅ _actions.Gameplay.Enable() in OnEnable
❌ Forgetting Unsubscribe in OnDisable
Memory leak — events call into destroyed objects
✅ Always mirror Subscribe/Unsubscribe with OnEnable/OnDisable