Unity Input System (new)
Read input through Unity's Input System package (com.unity.inputsystem, 1.x) — action-based, device-agnostic, rebindable. Targets Unity 6.3 LTS. This is the modern replacement for the legacy Input.GetAxis/Input.GetKey Input Manager.
When to use
- Use when setting up movement/jump/fire input, defining an
.inputactionsasset with - Use when
Packages/manifest.jsoncontainscom.unity.inputsystemor the project has an
action maps and control schemes, wiring a PlayerInput component, reading a Vector2 stick/WASD value, or handling gamepad + keyboard + touch from one set of actions.
*.inputactions asset.
**When *not* to use:** rebindable-control *architecture* across engines → input-systems (this skill is the Unity-specific API). Moving the character once you have the input vector → unity-physics / unity-csharp-scripting.
Core workflow
- Check Active Input Handling (Project Settings → Player). The package only receives
- Create an
.inputactionsasset. Add an *action map* (e.g.Gameplay), add *actions* - Choose how to read it:
input when this is Input System Package (New) or Both. Both is required if any old Input.GetAxis code remains.
(Move = Value/Vector2, Jump = Button, Fire = Button), and bind them to controls and composite bindings (WASD = 2D Vector composite).
PlayerInputcomponent (designer-friendly) — drop it on the player, point it at the- Direct in code (
InputActionReference/InputActionAsset) — most control; you
asset, pick a *Behavior* (Send Messages / Broadcast / Invoke Unity Events / Invoke C# Events). Best for single/local-coop players.
Enable() actions and read them. Best for systems and tools.
- Enable the actions/maps you read.
PlayerInputenables its default map automatically; - Switch action maps for context (gameplay ↔ UI/menu) instead of guarding every handler.
- Verify with the Input Debugger (Window → Analysis → Input Debugger) to confirm devices
actions you reference yourself must be .Enable()d (and disabled on teardown).
and that actions fire.
Patterns
1. PlayerInput with "Send Messages" (handlers on the same GameObject)
using UnityEngine;
using UnityEngine.InputSystem;
// PlayerInput (Behavior = Send Messages) calls On<ActionName>(InputValue) by name.
public class PlayerInputReceiver : MonoBehaviour
{
private Vector2 _move;
private void OnMove(InputValue value) => _move = value.Get<Vector2>(); // Move action
private void OnJump(InputValue value) { if (value.isPressed) Jump(); } // Button action
private void Update() { /* drive movement from _move */ }
private void Jump() { }
}
2. Reading an action directly in code (polling a value)
using UnityEngine;
using UnityEngine.InputSystem;
public class DirectMover : MonoBehaviour
{
[SerializeField] private InputActionReference moveAction; // assign the Move action
private void OnEnable() => moveAction.action.Enable(); // REQUIRED or it reads zero
private void OnDisable() => moveAction.action.Disable();
private void Update()
{
Vector2 move = moveAction.action.ReadValue<Vector2>(); // continuous value
transform.Translate(new Vector3(move.x, 0, move.y) * (5f * Time.deltaTime));
}
}
3. Event callbacks + switching action maps (gameplay ↔ UI)
[SerializeField] private InputActionAsset actions;
private void OnEnable()
{
actions.FindAction("Gameplay/Fire").performed += OnFire; // edge event: fires once
actions.FindActionMap("Gameplay").Enable();
}
private void OnDisable() => actions.FindAction("Gameplay/Fire").performed -= OnFire;
private void OnFire(InputAction.CallbackContext ctx) => Shoot(); // ctx.ReadValue<T>() if needed
private void OpenPauseMenu() // change context, don't sprinkle if-checks
{
actions.FindActionMap("Gameplay").Disable();
actions.FindActionMap("UI").Enable();
}
private void Shoot() { }
Pitfalls
- No input at all → either Active Input Handling is still
Input Manager (Old), or you InvalidOperationExceptionabout the old input backend → some script still calls- Buttons read as 0 with
ReadValue→ button *presses* are edge events; use the Send Messageshandlers never fire → the receiving script must be on the *same*- Leaking subscriptions → unsubscribe (
-=) inOnDisable; re-subscribing inOnEnable - Touch/gamepad not detected → enable the matching control scheme and confirm the device
forgot to Enable() the action/map. PlayerInput auto-enables; raw InputActions do not.
Input.GetAxis/Input.GetKey while Active Input Handling is New. Port it or set Both.
performed callback (or WasPressedThisFrame()), not per-frame ReadValue for triggers.
GameObject as the PlayerInput; Broadcast Messages reaches children too.
without unsubscribing doubles up handlers.
in the Input Debugger; the Vector2 composite needs all four bindings set.
References
- For interactive control rebinding (
PerformInteractiveRebinding), saving/loading - Primary docs: Unity Manual "Input System"
bindings as JSON, and local multiplayer with PlayerInputManager, read references/rebinding.md.
(https://docs.unity3d.com/Manual/com.unity.inputsystem.html).
Related skills
input-systems— engine-agnostic input architecture (rebinding, buffering, multi-device).unity-csharp-scripting— the MonoBehaviour these handlers live in.unity-physics— applying the input vector to a Rigidbody.