Receber por email
← Voltar para o catálogo

input-system

New Input System — action maps, PlayerInput component, generated C# classes, runtime rebinding, multi-device support, input buffering.

21estrelas
Atualizado há 6 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add XeldarAlz/everything-claude-unity

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/input-system/svg)](https://www.skillteca.com.br/skills/input-system)
#ai

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Unity New Input System

Input Action Asset Setup

Create an Input Action Asset: Assets > Create > Input Actions. This is the central configuration for all input bindings.

Action Map Structure

Organize actions into maps based on context:

PlayerControls.inputactions
  |-- Player (gameplay)
  |     |-- Move (Value, Vector2)
  |     |-- Look (Value, Vector2)
  |     |-- Jump (Button)
  |     |-- Attack (Button)
  |     |-- Interact (Button)
  |
  |-- UI (menu navigation)
  |     |-- Navigate (Value, Vector2)
  |     |-- Submit (Button)
  |     |-- Cancel (Button)
  |
  |-- Menu (pause/settings)
        |-- Pause (Button)

Action Types

  • Button: Discrete press/release. Use for jump, attack, interact.
  • Value: Continuous value. Use for movement, look, triggers.
  • Pass-Through: Like Value but does not perform initial state check. Use for multi-device scenarios.

Generated C# Class Workflow

In the Input Action Asset inspector, check "Generate C# Class" and click Apply. This is the recommended approach.

using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private PlayerControls _controls;
    private Vector2 _moveInput;

    private void Awake()
    {
        _controls = new PlayerControls();
    }

    private void OnEnable()
    {
        _controls.Player.Enable();

        _controls.Player.Move.performed += OnMove;
        _controls.Player.Move.canceled += OnMove;
        _controls.Player.Jump.performed += OnJump;
        _controls.Player.Attack.performed += OnAttack;
    }

    private void OnDisable()
    {
        _controls.Player.Move.performed -= OnMove;
        _controls.Player.Move.canceled -= OnMove;
        _controls.Player.Jump.performed -= OnJump;
        _controls.Player.Attack.performed -= OnAttack;

        _controls.Player.Disable();
    }

    private void OnMove(InputAction.CallbackContext ctx)
    {
        _moveInput = ctx.ReadValue<Vector2>();
    }

    private void OnJump(InputAction.CallbackContext ctx)
    {
        // Jump logic
    }

    private void OnAttack(InputAction.CallbackContext ctx)
    {
        // Attack logic
    }

    private void Update()
    {
        transform.Translate(new Vector3(_moveInput.x, 0, _moveInput.y) * Time.deltaTime * 5f);
    }
}

PlayerInput Component

The PlayerInput component provides an easier but less flexible approach.

Behavior Modes

| Mode | Pros | Cons | |------|------|------| | Send Messages | Simple, no setup | Uses SendMessage (slow, no type safety) | | Broadcast Messages | Reaches child objects | Same issues as SendMessages | | Invoke Unity Events | Inspector-assigned, flexible | Requires wiring in Inspector | | Invoke C# Events | Best performance, type-safe | Requires code subscription |

Using Invoke C# Events

using UnityEngine;
using UnityEngine.InputSystem;

[RequireComponent(typeof(PlayerInput))]
public class PlayerInputHandler : MonoBehaviour
{
    private PlayerInput _playerInput;

    private void Awake()
    {
        _playerInput = GetComponent<PlayerInput>();
    }

    private void OnEnable()
    {
        _playerInput.onActionTriggered += OnActionTriggered;
    }

    private void OnDisable()
    {
        _playerInput.onActionTriggered -= OnActionTriggered;
    }

    private void OnActionTriggered(InputAction.CallbackContext ctx)
    {
        switch (ctx.action.name)
        {
            case "Move":
                HandleMove(ctx.ReadValue<Vector2>());
                break;
            case "Jump":
                if (ctx.performed) HandleJump();
                break;
        }
    }

    private void HandleMove(Vector2 input) { /* ... */ }
    private void HandleJump() { /* ... */ }
}

Reading Input Values

Callback Phases

action.started += ctx => { };   // Input begins (button starts pressing)
action.performed += ctx => { }; // Input completes (button fully pressed)
action.canceled += ctx => { };  // Input released

Polling in Update (Alternative)

private void Update()
{
    // Polling approach — simpler but less event-driven
    Vector2 move = _controls.Player.Move.ReadValue<Vector2>();
    bool jumpPressed = _controls.Player.Jump.WasPressedThisFrame();
    bool jumpReleased = _controls.Player.Jump.WasReleasedThisFrame();
    bool jumpHeld = _controls.Player.Jump.IsPressed();
}

Action Map Switching

public class InputMapSwitcher : MonoBehaviour
{
    private PlayerControls _controls;

    public void SwitchToUI()
    {
        _controls.Player.Disable();
        _controls.UI.Enable();
    }

    public void SwitchToGameplay()
    {
        _controls.UI.Disable();
        _controls.Player.Enable();
    }

    public void SwitchToMenu()
    {
        _controls.Player.Disable();
        _controls.UI.Disable();
        _controls.Menu.Enable();
    }
}

Composite Bindings

2D Vector Composite (WASD / D-Pad)

In the Input Action Asset, add a 2D Vector composite to a Vector2 action:

  • Up: W / D-Pad Up
  • Down: S / D-Pad Down
  • Left: A / D-Pad Left
  • Right: D / D-Pad Right

Button With Modifier

For key combos like Ctrl+S:

  • Add ButtonWithOneModifier composite
  • Modifier: Left Ctrl
  • Button: S

Runtime Rebinding

using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;

public class RebindManager : MonoBehaviour
{
    [SerializeField] private InputActionReference actionToRebind;
    [SerializeField] private TMP_Text bindingDisplayText;
    [SerializeField] private GameObject waitingForInputUI;

    private InputActionRebindingExtensions.RebindingOperation _rebindOperation;

    public void StartRebinding()
    {
        actionToRebind.action.Disable();
        waitingForInputUI.SetActive(true);

        _rebindOperation = actionToRebind.action.PerformInteractiveRebinding()
            .WithControlsExcluding("Mouse") // Exclude mouse movement
            .WithCancelingThrough("<Keyboard>/escape")
            .OnMatchWaitForAnother(0.1f) // Debounce
            .OnComplete(operation => RebindComplete())
            .OnCancel(operation => RebindCanceled())
            .Start();
    }

    private void RebindComplete()
    {
        _rebindOperation.Dispose();
        _rebindOperation = null;
        waitingForInputUI.SetActive(false);

        actionToRebind.action.Enable();
        UpdateBindingDisplay();

        // Save the binding override
        string rebinds = actionToRebind.action.actionMap.asset.SaveBindingOverridesAsJson();
        PlayerPrefs.SetString("InputBindings", rebinds);
    }

    private void RebindCanceled()
    {
        _rebindOperation.Dispose();
        _rebindOperation = null;
        waitingForInputUI.SetActive(false);
        actionToRebind.action.Enable();
    }

    private void UpdateBindingDisplay()
    {
        int bindingIndex = actionToRebind.action.GetBindingIndexForControl(
            actionToRebind.action.controls[0]);
        bindingDisplayText.text = InputControlPath.ToHumanReadableString(
            actionToRebind.action.bindings[bindingIndex].effectivePath,
            InputControlPath.HumanReadableStringOptions.OmitDevice);
    }

    public void LoadSavedBindings()
    {
        string rebinds = PlayerPrefs.GetString("InputBindings", string.Empty);
        if (!string.IsNullOrEmpty(rebinds))
        {
            actionToRebind.action.actionMap.asset.LoadBindingOverridesFromJson(rebinds);
        }
    }
}

Input Buffering Pattern

Buffer inputs so actions like jump register even if pressed slightly before landing.

public class InputBuffer : MonoBehaviour
{
    [SerializeField] private float bufferDuration = 0.15f;

    private float _jumpBufferTimer;
    private bool _jumpConsumed;

    private void Update()
    {
        if (_jumpBufferTimer > 0f)
        {
            _jumpBufferTimer -= Time.deltaTime;
        }
    }

    // Called from input callback
    public void OnJumpPressed()
  
Compartilhar X LinkedIn