Quick answer: The most common cause is that the Input Actions asset is not assigned to the PlayerInput component, or the action map is not enabled at runtime.

Here is how to fix Unity input system not working. You installed Unity's New Input System package, created an Input Actions asset, wrote a script to read player input — and nothing happens. No movement, no button presses, no response at all. The old Input.GetAxis() calls threw errors after the switch, so you know the new system is active, but your actions refuse to fire. This is one of the most common friction points when migrating to the New Input System, and it almost always traces back to one of a few specific configuration gaps.

The Symptom

You have set up an Input Actions asset with action maps for movement and gameplay. Your script references these actions and attempts to read their values every frame. But at runtime, ReadValue<Vector2>() always returns (0, 0), callback methods like OnMove or OnJump are never invoked, and your character stands completely still regardless of keyboard, gamepad, or mouse input.

There are no errors in the Console. The Input Debugger window (Window > Analysis > Input Debugger) shows that devices are connected and the keyboard registers key presses. But the actions themselves show no activity. The input hardware works — the system just is not routing it to your actions.

If you are migrating from the old Input Manager, you may also see InvalidOperationException errors on any remaining Input.GetAxis() or Input.GetKeyDown() calls, confirming that the old system is disabled but not yet fully replaced.

What Causes This

There are five common causes, and most projects hit at least two of them simultaneously during migration:

1. Active Input Handling is still set to the old system. Unity supports running the old Input Manager, the new Input System, or both simultaneously. If Project Settings still points to the old Input Manager, the new system's classes exist in code but do not receive any input events from the engine. This is a project-level toggle, not a per-scene setting.

2. The PlayerInput component is missing or misconfigured. If you are using the PlayerInput component workflow (the recommended approach for most projects), you need a PlayerInput component on a GameObject in the scene with the Input Actions asset assigned and the correct Default Map selected. Without this, there is no bridge between the input hardware and your action callbacks.

3. Action maps are not enabled. If you are using the code-driven workflow instead of PlayerInput, you must explicitly enable your action map or individual actions at runtime. Creating an instance of your generated C# class does not automatically enable its actions — you need to call .Enable() on the map or the entire asset.

4. Wrong action type for the input you expect. The Input System has three action types: Button, Value, and PassThrough. A movement action set to Button type will not continuously report axis values. A jump action set to Value type with a Vector2 control type will not fire started callbacks on key presses the way you expect. Mismatched action types cause silent failures where the binding exists but the action never triggers in the way your code listens for it.

5. The generated C# class is out of date. If you modified your Input Actions asset (added bindings, renamed actions, changed action types) but did not regenerate the C# wrapper class, your code references stale action definitions. The asset and the code are out of sync, and actions may silently fail to match.

The Fix

Step 1: Verify and configure Active Input Handling. Go to Edit > Project Settings > Player > Other Settings and find the Active Input Handling dropdown. Set it to Input System Package (New) if you have fully migrated, or Both if you still need the old Input Manager for some systems. Unity will prompt you to restart the editor.

// After switching, verify the new system is active
// This should NOT throw an error if the new system is enabled
using UnityEngine;
using UnityEngine.InputSystem;

public class InputSystemCheck : MonoBehaviour
{
    void Start()
    {
        // List all connected devices via the new Input System
        foreach (var device in InputSystem.devices)
        {
            Debug.Log($"Device: {device.displayName} ({device.GetType().Name})");
        }

        // If this throws, the old system is still active
        var keyboard = Keyboard.current;
        Debug.Log($"Keyboard present: {keyboard != null}");
    }
}

If InputSystem.devices is empty or the UnityEngine.InputSystem namespace is not found, the package is not installed. Open Package Manager (Window > Package Manager), search for "Input System" in the Unity Registry, and install it.

Step 2: Set up PlayerInput correctly or enable actions in code. If you are using the PlayerInput component approach, add a PlayerInput component to your player GameObject, assign your Input Actions asset, and select the correct Default Map. Then choose a Behavior mode — Send Messages, Broadcast Messages, Invoke Unity Events, or Invoke C# Events.

// Option A: Using PlayerInput with Send Messages behavior
// Attach this script to the same GameObject as PlayerInput
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private Vector2 moveInput;

    // Called automatically by PlayerInput when using Send Messages
    public void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
        Debug.Log($"Move input: {moveInput}");
    }

    // Called automatically when the Jump action is triggered
    public void OnJump(InputValue value)
    {
        Debug.Log("Jump pressed!");
    }

    void FixedUpdate()
    {
        transform.Translate(new Vector3(moveInput.x, 0, moveInput.y) * 5f * Time.fixedDeltaTime);
    }
}
// Option B: Using the generated C# class directly (no PlayerInput component)
using UnityEngine;
using UnityEngine.InputSystem;

public class PlayerController : MonoBehaviour
{
    private PlayerInputActions inputActions;
    private Vector2 moveInput;

    void Awake()
    {
        inputActions = new PlayerInputActions();
    }

    void OnEnable()
    {
        // CRITICAL: You must enable the action map!
        inputActions.Gameplay.Enable();

        // Subscribe to action callbacks
        inputActions.Gameplay.Move.performed += ctx => moveInput = ctx.ReadValue<Vector2>();
        inputActions.Gameplay.Move.canceled += ctx => moveInput = Vector2.zero;
        inputActions.Gameplay.Jump.performed += ctx => OnJump();
    }

    void OnDisable()
    {
        inputActions.Gameplay.Disable();
    }

    private void OnJump()
    {
        Debug.Log("Jump performed!");
    }

    void FixedUpdate()
    {
        transform.Translate(new Vector3(moveInput.x, 0, moveInput.y) * 5f * Time.fixedDeltaTime);
    }
}

The most common mistake with Option B is forgetting the .Enable() call. Without it, the action map exists but does not listen for any input. Always enable in OnEnable() and disable in OnDisable() to follow Unity's component lifecycle correctly.

Step 3: Use the correct action types and read values properly. Open your Input Actions asset and verify each action's type:

// Reading different action types correctly
using UnityEngine;
using UnityEngine.InputSystem;

public class InputReader : MonoBehaviour
{
    [SerializeField] private InputActionReference moveActionRef;
    [SerializeField] private InputActionReference jumpActionRef;
    [SerializeField] private InputActionReference lookActionRef;

    void OnEnable()
    {
        moveActionRef.action.Enable();
        jumpActionRef.action.Enable();
        lookActionRef.action.Enable();
    }

    void OnDisable()
    {
        moveActionRef.action.Disable();
        jumpActionRef.action.Disable();
        lookActionRef.action.Disable();
    }

    void Update()
    {
        // Value action: read continuously
        Vector2 move = moveActionRef.action.ReadValue<Vector2>();

        // Button action: check if triggered this frame
        if (jumpActionRef.action.WasPressedThisFrame())
        {
            Debug.Log("Jump!");
        }

        // Value action for mouse delta
        Vector2 look = lookActionRef.action.ReadValue<Vector2>();
    }
}

If you set a movement action to Button type, ReadValue<Vector2>() will always return zero because Button actions only report a float (pressed = 1, released = 0), not a Vector2. This is the silent failure that catches most developers.

After changing action types in the asset, remember to click Save Asset in the Input Actions editor, and if you are using a generated C# class, click Generate C# Class to regenerate the wrapper.

Related Issues

If your input works but physics-based movement does not respond, see our guide on AddForce not working on Rigidbody, which covers FixedUpdate timing and force application. If your game builds successfully but controls stop working in the built player, check Build Missing Scenes or Resources — Input Action assets sometimes fail to get included in builds if they are not properly referenced.

Forgot to call .Enable() on your action map? You are not alone.