mcpField
U
unity-input

unity-input

github.com/nice-wolf-studioDevelopment4075 installsUpdated 6w ago
Repository

About unity-input

unity-input is a guide to Unity's Input System for developers, covering action-based input setup and reading alongside the legacy Input Manager. It includes multiple devices, local multiplayer, interactions, touch, and runtime rebinding.

Key features

  1. 01InputAction and Action Maps
  2. 02PlayerInput local multiplayer management
  3. 03Polling and event-driven input
  4. 04Keyboard, gamepad, mouse, and touch
  5. 05Input interactions and processors
  6. 06Runtime rebinding and device discovery

Use cases

  1. 01Configuring player controls across devices
  2. 02Switching between gameplay and UI action maps
  3. 03Assigning devices for local multiplayer
  4. 04Adding runtime control rebinding

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/nice-wolf-studio/unity-claude-skills --skill unity-input

After installing, type/unity-inputin Claude Code to confirm it loaded.

Bundled filesreferences/input-system-api.md

Details

From the project README

Unity Input System

Input System Overview: New vs Legacy

Unity provides two input systems:

FeatureNew Input System (Recommended)Legacy Input Manager
Packagecom.unity.inputsystem (v1.19.0 for Unity 6.3)Built-in (UnityEngine.Input)
ArchitectureAction-based, event-drivenPolling-based
Device SupportGamepad, keyboard, mouse, touch, XR, customKeyboard, mouse, joystick
MultiplayerBuilt-in local multiplayer via PlayerInputManual implementation
RebindingRuntime rebinding supportNot supported
Cross-platformControl Schemes per device typeManual per-platform code

The new Input System is a package installed via Package Manager. It replaces the legacy Input.GetKey/Input.GetAxis API with an action-based model that separates input purpose from device controls.

Namespace: UnityEngine.InputSystem

Quick Start Setup

1. Install the Package

Install via Window > Package Manager > Unity Registry > Input System.

2. Create Default Project-Wide Actions

Go to Edit > Project Settings > Input System Package > Input Actions and click "Create and assign a default project-wide Action Asset".

This creates default Action Maps:

  • Player: Move, Look, Jump, Attack
  • UI: Navigate, Submit, Cancel

Each action includes bindings for keyboard, gamepad, XR controllers, and touchscreen.

3. Read Input in a Script
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    InputAction moveAction;
    InputAction jumpAction;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        jumpAction = InputSystem.actions.FindAction("Jump");
    }

    void Update()
    {
        Vector2 moveValue = moveAction.ReadValue<Vector2>();
        transform.Translate(new Vector3(moveValue.x, 0, moveValue.y) * Time.deltaTime * 5f);

        if (jumpAction.IsPressed())
        {
            // Jump logic
        }
    }
}

When multiple actions share names across maps, specify both: "Player/Move".

Input Actions and Action Maps

Core Concepts
  • InputAction: A named action that returns control values or triggers callbacks
  • InputActionMap: A named collection of related actions (e.g., "Player", "UI", "Vehicle")
  • InputBinding: Relationship between an action and a device control
  • InputSystem.actions: Reference to project-wide actions
Creating Actions

Method 1 — Input Actions Editor (Recommended): Configure via Project Settings > Input System Package.

Method 2 — MonoBehaviour fields: Declare InputAction fields directly in scripts (configurable in Inspector).

Method 3 — Code:

var moveAction = new InputAction("Move", InputActionType.Value);
moveAction.AddCompositeBinding("Dpad")
    .With("Up", "<Keyboard>/w").With("Down", "<Keyboard>/s")
    .With("Left", "<Keyboard>/a").With("Right", "<Keyboard>/d");
moveAction.Enable();

Method 4 — JSON: var map = InputActionMap.FromJson(jsonString);

Action Lifecycle

Actions begin disabled. You must call .Enable() before they respond to input. You cannot modify bindings while enabled; call .Disable() first.

Input Action Assets (.inputactions)

These are JSON files storing actions, bindings, and control schemes. Create via Assets > Create > Input Actions.

Auto-generated C# class: Enable "Generate C# Class" in the asset's importer to get type-safe access:

public class MyPlayerScript : MonoBehaviour, IGameplayActions
{
    MyPlayerControls controls;

    public void OnEnable()
    {
        controls = new MyPlayerControls();
        controls.gameplay.SetCallbacks(this);
        controls.gameplay.Enable();
    }

    public void OnDisable()
    {
        controls.gameplay.Disable();
    }

    public void OnMove(InputAction.CallbackContext context)
    {
        Vector2 move = context.ReadValue<Vector2>();
        // Handle movement
    }
}

PlayerInput Component

The PlayerInput component maps Input Actions to script methods and handles local multiplayer with device filtering and screen-splitting.

Setup
  1. Add PlayerInput component to your player GameObject
  2. Assign your Action Asset to the Actions field
  3. Select a Default Action Map
  4. Choose a Behavior notification type
Behavior Options
BehaviorMechanismBest For
Send MessagesGameObject.SendMessage()Simple prototyping
Broadcast MessagesBroadcastMessage() down hierarchyComponent hierarchies
Invoke Unity EventsInspector-configured event routingDesigner-friendly wiring
Invoke C# EventsonActionTriggered, onDeviceLost, onDeviceRegainedProgrammer control
Send Messages Pattern
public class PlayerActions : MonoBehaviour
{
    public void OnJump()
    {
        // Called when Jump action triggers (no parameters)
    }

    public void OnMove(InputValue value)
    {
        Vector2 v = value.Get<Vector2>();
        // InputValue is only valid during this callback
    }
}
Unity Events Pattern
public void OnFire(InputAction.CallbackContext context)
{
    if (context.performed)
    {
        // Fire logic
    }
}
Managing PlayerInput
PlayerInput playerInput = GetComponent<PlayerInput>();
playerInput.DeactivateInput();                      // Disable all input
playerInput.ActivateInput();                         // Re-enable with default map
playerInput.SwitchCurrentActionMap("Vehicle");       // Switch action map

Reading Input in Code

Polling (in Update)
// 2D movement axis
Vector2 move = moveAction.ReadValue<Vector2>();

// Button state
if (jumpAction.IsPressed()) { /* held down */ }
if (jumpAction.WasPressedThisFrame()) { /* just pressed */ }
if (jumpAction.WasReleasedThisFrame()) { /* just released */ }
Callbacks (Event-Driven)
void OnEnable()
{
    fireAction.started += OnFireStarted;
    fireAction.performed += OnFirePerformed;
    fireAction.canceled += OnFireCanceled;
    fireAction.Enable();
}

void OnDisable()
{
    fireAction.started -= OnFireStarted;
    fireAction.performed -= OnFirePerformed;
    fireAction.canceled -= OnFireCanceled;
    fireAction.Disable();
}

void OnFireStarted(InputAction.CallbackContext ctx) { /* Input began */ }
void OnFirePerformed(InputAction.CallbackContext ctx) { /* Completed */ }
void OnFireCanceled(InputAction.CallbackContext ctx) { /* Interrupted */ }

Gamepad / Keyboard / Mouse / Touch

Gamepad
using UnityEngine.InputSystem;

// Current gamepad (null if none connected)
var gp = Gamepad.current;
if (gp == null) return;

Vector2 leftStick = gp.leftStick.ReadValue();
bool southPressed = gp.buttonSouth.isPressed;

// Access by enum
gp[GamepadButton.LeftShoulder].isPressed;
gp[GamepadButton.Y].isPressed;          // Xbox style
gp[GamepadButton.Triangle].isPressed;   // PlayStation style

// Rumble / Haptics
gp.SetMotorSpeeds(0.25f, 0.75f); // low-frequency, high-frequency
gp.ResetHaptics();

// Global haptics control
InputSystem.PauseHaptics();
InputSystem.ResumeHaptics();
InputSystem.ResetHaptics();

Supported gamepads: DualShock 3/4, DualSense, Xbox (XInput/Bluetooth), Switch Pro. Generic HID gamepads appear as generic joysticks, not Gamepad devices.

Keyboard and Mouse
var kb = Keyboard.current;
if (kb.spaceKey.wasPressedThisFrame) { /* space pressed */ }

var mouse = Mouse.current;
Vector2 mousePos = mouse.position.ReadValue();
float scroll = mouse.scroll.ReadValue().y;
bool leftClick = mouse.leftButton.isPressed;
Touch

Two API levels:

Low-level — Touchscreen device:

var ts = Touchscreen.current;
if (ts.primaryTouch.press.isPressed)
{
    Vector2 pos = ts.primaryTouch.position.ReadValue();
}

High-level — EnhancedTouch API:

using UnityEngine.InputSystem.EnhancedTouch;

void OnEnable() => EnhancedTouchSupport.Enable();
void OnDisable() => EnhancedTouchSupport.Disable();

void Update()
{
    foreach (var touch in Touch.activeTouches)
    {
        Debug.Log($"{touch.touchId}: {touch.screenPosition}, {touch.phase}");
    }
}

Touch phases: Began, Moved, Stationary, Ended, Cancelled.

Multi-touch with Actions: Bind <Touchscreen>/touch*/press and set action type to PassThrough to receive callbacks per touch.

Touch simulation: Enable via TouchSimulation.Enable() to simulate touch from mouse/pen during development.

Device Discovery
// Monitor device connections
InputSystem.onDeviceChange += (device, change) =>
{
    if (change == InputDeviceChange.Added)
        Debug.Log($"Device connected: {device.displayName}");
};

Interactions and Processors

Interactions define input patterns that drive action phases.

Interaction Phases
PhaseMeaning
WaitingAwaiting input
StartedInput received, not yet complete
PerformedInteraction complete — primary response trigger
CanceledInteraction interrupted
Built-in Interactions
InteractionDescriptionKey Parameters
DefaultAuto-applied; behavior varies by action type—
PressExplicit button press behaviorpressPoint, behavior (PressOnly/ReleaseOnly/PressAndRelease)
HoldSustained press for minimum durationduration, pressPoint
TapQuick press-and-releaseduration, pressPoint
SlowTapHold then releaseduration, pressPoint
MultiTapRepeated tap sequencestapTime, tapDelay, tapCount, pressPoint
Adding Interactions via Code
var action = new InputAction("fire");
action.AddBinding("<Gamepad>/buttonSouth")
    .WithInteractions("tap(duration=0.8)");
Tap vs Hold Example (Fire vs Charge)
var fireAction = new InputAction("fire");
fireAction.AddBinding("<Gamepad>/buttonSouth").WithInteractions("tap,slowTap");
fireAction.started += ctx => { if (ctx.interaction is SlowTapInteraction) ShowChargingUI(); };
fireAction.performed += ctx => {
    if (ctx.interaction is SlowTapInteraction) ChargedFire(); else Fire();
};
fireAction.canceled += _ => HideChargingUI();
fireAction.Enable();
Custom Interaction

Implement IInputInteraction, then register: InputSystem.RegisterInteraction<T>(). See references/input-system-api.md for full example.

Common Patterns

Action Map Switching (e.g., Gameplay vs UI)
public class GameStateManager : MonoBehaviour
{
    PlayerInput playerInput;

    void Start() => playerInput = GetComponent<PlayerInput>();

    public void EnterMenu() => playerInput.SwitchCurrentActionMap("UI");
    public void ExitMenu() => playerInput.SwitchCurrentActionMap("Player");
}
Runtime Rebinding
var rebindOp = action.PerformInteractiveRebinding()
    .WithControlsExcluding("Mouse")
    .OnMatchWaitForAnother(0.1f)
    .OnComplete(op =>
    {
        Debug.Log($"Rebound to: {op.action.bindings[0].effectivePath}");
        op.Dispose();
    })
    .Start();
Multiple Bindings for Same Action (WASD + Arrows)
var moveAction = new InputAction("Move", InputActionType.Value);
moveAction.AddCompositeBinding("2DVector")
    .With("Up", "<Keyboard>/w").With("Down", "<Keyboard>/s")
    .With("Left", "<Keyboard>/a").With("Right", "<Keyboard>/d");
moveAction.AddCompositeBinding("2DVector")
    .With("Up", "<Keyboard>/upArrow").With("Down", "<Keyboard>/downArrow")
    .With("Left", "<Keyboard>/leftArrow").With("Right", "<Keyboard>/rightArrow");

Anti-Patterns

Anti-PatternProblemCorrect Approach
Using Input.GetKey() (legacy)Not compatible with new Input System; no rebinding, no multi-deviceUse InputAction with bindings
Reading actions without .Enable()Actions start disabled and return no valuesAlways call action.Enable() in OnEnable()
Forgetting .Disable() on cleanupMemory leaks and ghost callbacksCall action.Disable() in OnDisable()
Modifying bindings while action is enabledThrows exceptionCall .Disable() before modifying, then .Enable()
Hardcoding device paths in gameplay codeBreaks cross-platform supportUse Actions + Control Schemes instead
Using InputValue outside its callbackValue is only valid during the callback frameCopy the value to a field immediately
Accessing Gamepad.current without null checkCrashes if no gamepad connectedAlways check if (Gamepad.current == null) return;
Not unsubscribing from action callbacksCauses errors on scene reloadUnsubscribe in OnDisable()
Using SendMessages behavior in productionPerformance overhead from reflectionUse Invoke Unity Events or Invoke C# Events
Polling EnhancedTouch without enabling itReturns empty collectionsCall EnhancedTouchSupport.Enable() first

Key API Quick Reference

APIPurpose
InputSystem.actionsProject-wide actions
InputSystem.actions.FindAction("name")Find action by name
action.ReadValue<T>()Read current value
action.IsPressed()Button held check
action.WasPressedThisFrame()Button just pressed
action.WasReleasedThisFrame()Button just released
action.Enable() / action.Disable()Activate/deactivate
action.started / performed / canceledCallback events
action.AddBinding("path")Add binding in code
action.AddCompositeBinding("type")Add composite (Dpad, 2DVector)
.WithInteractions("tap(duration=0.5)")Add interaction to binding
Gamepad.currentCurrent gamepad reference
Keyboard.current / Mouse.currentCurrent keyboard/mouse
Touchscreen.currentCurrent touchscreen
EnhancedTouchSupport.Enable()Enable enhanced touch API
Touch.activeTouchesAll active touches (enhanced)
InputSystem.onDeviceChangeDevice connection events
PlayerInput.SwitchCurrentActionMap()Change active action map
action.PerformInteractiveRebinding()Start runtime rebinding

Related Skills

  • unity-scripting — MonoBehaviour lifecycle, C# patterns
  • unity-ui — UI Toolkit input integration, InputSystemUIInputModule
  • unity-xr — XR controller input, tracked devices

Additional Resources

Comments

Markdown supported