Imported from gamedev-skills/awesome-gamedev-agent-skills (
skills/unity/unity-input-system/SKILL.md) via skills.sh. Install upstream withnpx skills add gamedev-skills/awesome-gamedev-agent-skills --skill unity-input-system. Copyright stays with the author.
Unity Input System (new)
Read input through Unity's Input System package (com.unity.inputsystem 1.x; Unity 6.3 LTS
ships 1.20) — 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 action maps and control schemes, wiring aPlayerInputcomponent, reading aVector2stick/WASD value, or handling gamepad + keyboard + touch from one set of actions. - Use when
Packages/manifest.jsoncontainscom.unity.inputsystemor the project has an*.inputactionsasset.
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
input when this is
Input System Package (New)orBoth.Bothis required if any oldInput.GetAxiscode remains. - Find or create the
.inputactionsasset. New Unity 6 projects usually already have one assigned as the project-wide actions (Project Settings → Input System Package; the template file isInputSystem_Actions.inputactions) — reuse it rather than adding a second asset. Add an action map (e.g.Gameplay), add actions (Move= Value/Vector2,Jump= Button,Fire= Button), and bind them to controls and composite bindings (WASD = 2D Vector composite). - Choose how to read it:
PlayerInputcomponent (designer-friendly) — drop it on the player, point it at the asset, pick a Behavior (Send Messages / Broadcast / Invoke Unity Events / Invoke C# Events). Best for single/local-coop players.- Project-wide actions in code (
InputSystem.actions.FindAction("Move")) — no asset reference to wire up, and the actions are already enabled. - Direct in code (
InputActionReference/InputActionAsset) — most control; youEnable()actions and read them. Best for systems and tools.
- Enable the actions/maps you read.
PlayerInputenables its default map automatically and project-wide actions start enabled; actions from any other asset must be.Enable()d (and disabled on teardown). - 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 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. Project-wide actions (no asset reference)
using UnityEngine;
using UnityEngine.InputSystem;
public class ProjectWideMover : MonoBehaviour
{
private InputAction _move, _jump;
private void Awake()
{
// Looked up once; project-wide actions are preloaded and enabled by default.
_move = InputSystem.actions.FindAction("Move");
_jump = InputSystem.actions.FindAction("Jump");
}
private void Update()
{
Vector2 move = _move.ReadValue<Vector2>();
if (_jump.WasPressedThisFrame()) { /* jump */ }
}
}
4. 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 forgot toEnable()the action/map.PlayerInputand project-wide actions start enabled; actions from other assets do not. - Gameplay actions fire while a menu is open → project-wide actions enable every action
map at startup, including when
PlayerInputuses that asset. InStart, disable the maps you do not want (InputSystem.actions.FindActionMap("UI").Disable()) and enable only the current one. FindActionreturns null → the name (orMap/Actionpath) does not exist in that asset. Check the spelling in the Actions Editor; with project-wide actions, make sure the asset you edited is the one assigned in Project Settings → Input System Package.InvalidOperationExceptionabout the old input backend → some script still callsInput.GetAxis/Input.GetKeywhile Active Input Handling isNew. Port it or setBoth.- Buttons read as 0 with
ReadValue→ button presses are edge events; use theperformedcallback (orWasPressedThisFrame()), not per-frameReadValuefor triggers. Send Messageshandlers never fire → the receiving script must be on the same GameObject as thePlayerInput;Broadcast Messagesreaches children too.- Leaking subscriptions → unsubscribe (
-=) inOnDisable; re-subscribing inOnEnablewithout unsubscribing doubles up handlers. - Touch/gamepad not detected → enable the matching control scheme and confirm the device in the Input Debugger; the Vector2 composite needs all four bindings set.
References
- For interactive control rebinding (
PerformInteractiveRebinding), saving/loading bindings as JSON, and local multiplayer withPlayerInputManager, readreferences/rebinding.md. - Primary docs: Unity Manual "Input System"
(
https://docs.unity3d.com/Manual/com.unity.inputsystem.html) and the package manual (https://docs.unity3d.com/Packages/com.unity.inputsystem@1.20/manual/index.html), including "About project-wide actions".
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.
