Overview
Tested with: Unity 2022.3 LTS / Unity 6
"I want controls that work with both keyboard and gamepad." "I want players to be able to customize their key bindings." If you have ever struggled to achieve these goals with the old Input System, the New Input System is here to help.
New Input System is the next-generation input handling system introduced in Unity 2019. It uses an abstracted concept called Input Actions to achieve flexible, device-independent input processing.
Installation and Initial Setup
Installing the Package
- Open
Window > Package Manager - Select
Unity Registryfrom the dropdown at the top-left - Search for
Input Systemand install it - Click "Yes" when prompted to restart
Configuring Active Input Handling
- Open
Edit > Project Settings > Player - Check
Other Settings > Configuration > Active Input Handling - Select Both or Input System Package (New)
- The Editor will restart
Both: Allows using both the old and new Input Systems simultaneously. Useful during the migration period.
Differences from the Old Input System
Problems with the Old Input System
- Required separate code for each device
- Difficult to customize key bindings
- Cross-platform support was cumbersome
- Local multiplayer was difficult to implement
Advantages of the New Input System
- Device-independent implementation - Same code works across multiple devices
- Cross-platform support - Centrally managed via configuration files
- Key binding customization - Provided as a built-in feature
- Local multiplayer support - Easily implemented with the Player Input component
- Complex input patterns - Long press, double-click, etc. achieved through configuration alone
Components of the New Input System
| Element | Description |
|---|---|
| Input Actions Asset | A file that stores input configuration |
| Action Map | A group of related Actions |
| Action | A unit of operation (movement, jump, etc.) |
| Binding | Links an Action to an actual input device |
| Player Input | A component that receives input events |
Action Type
| Type | Use Case |
|---|---|
| Value | Continuous values (movement stick, triggers, etc.) |
| Button | Button press state (jump, attack, etc.) |
| Pass-through | Passes input directly (handling multiple input sources) |
Creating and Configuring Input Actions
Creating an Input Actions Asset
- Right-click in the Project window
- Select
Create > Input Actions - Double-click the asset to open the editing window
Creating an Action Map
Click the + button at the top-left to add a new Action Map (e.g., "Player")
Creating an Action
- Click the
+button with an Action Map selected - Enter an Action name (e.g., "Move", "Jump")
- Configure the Action Type and Control Type
Adding Bindings
Example for WASD keys:
- Select the "Move" Action
- Click
+and chooseAdd Up/Down/Left/Right Composite - Set Up: W, Down: S, Left: A, Right: D
Adding a gamepad left stick:
- Select the same "Move" Action
- Click
+and chooseAdd Binding - Select
Gamepad > Left Stickin the Path
Multi-device support: By adding multiple Bindings to the same Action, the same code works for both keyboard and gamepad.
Generating a C# Class (Recommended)
You can auto-generate a type-safe class from the Input Actions Asset.
- Select the Input Actions Asset in the Project window
- Check Generate C# Class in the Inspector
- Set the Class Name (e.g.,
PlayerInputActions) - Optionally set a Namespace
- Click Apply
This generates PlayerInputActions.cs, which can be instantiated with new PlayerInputActions().
Script Implementation
Choosing the Right Approach
| Method | Best For |
|---|---|
| Player Input + Unity Events | Small projects, prototyping, when non-programmers need to modify settings |
| C# Class Generation | Medium to large projects, type-safe implementation, complex input handling |
Method 1: Player Input + Unity Events
The Player Input component lets you link Actions to methods in the Inspector.
Configuring the Player Input Component
- Add a
Player Inputcomponent to the GameObject - Set the
Actionsto the Input Actions Asset - Change
Behaviorto Unity Events - An
Eventssection appears - Register methods for each Action
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private Vector2 moveInput;
public void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
public void OnJump(InputAction.CallbackContext context)
{
if (context.performed)
{
Debug.Log("Jump!");
}
}
}
Method 2: C# Class Generation (Recommended)
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private PlayerInputActions inputActions;
private Vector2 moveInput;
void Awake()
{
inputActions = new PlayerInputActions();
inputActions.Player.Move.performed += OnMove;
inputActions.Player.Move.canceled += OnMove;
inputActions.Player.Jump.performed += OnJump;
}
void OnEnable() => inputActions.Enable();
void OnDisable() => inputActions.Disable();
void OnDestroy()
{
// Unsubscribe event handlers (prevent memory leaks)
inputActions.Player.Move.performed -= OnMove;
inputActions.Player.Move.canceled -= OnMove;
inputActions.Player.Jump.performed -= OnJump;
inputActions.Dispose();
}
private void OnMove(InputAction.CallbackContext context)
{
moveInput = context.ReadValue<Vector2>();
}
private void OnJump(InputAction.CallbackContext context)
{
Debug.Log("Jump!");
}
}
Preventing memory leaks: Unsubscribe event handlers with
-=inOnDestroyand callDispose()to prevent memory leaks when the object is destroyed.
Switching Action Maps
You can switch the active Action Map between gameplay and UI operations.
public class InputManager : MonoBehaviour
{
private PlayerInputActions inputActions;
void Awake()
{
inputActions = new PlayerInputActions();
}
// During gameplay: Enable Player map, Disable UI map
public void EnableGameplayInput()
{
inputActions.Player.Enable();
inputActions.UI.Disable();
}
// During UI interaction: Enable UI map, Disable Player map
public void EnableUIInput()
{
inputActions.Player.Disable();
inputActions.UI.Enable();
}
}
Example use case: Switch to the UI map when the pause menu is opened, and switch back to the Player map when it is closed. This prevents the character from moving during menu navigation.
Interactions and Processors
Interactions
| Interaction | Use Case |
|---|---|
| Hold | Fires on long press |
| Tap | Detects short taps |
| Multi Tap | Detects consecutive taps such as double-click |
Processors
| Processor | Use Case |
|---|---|
| Normalize | Normalizes vectors (corrects diagonal movement speed) |
| Invert | Inverts input values |
| Scale | Scales input values (sensitivity adjustment) |
| Dead Zone | Ignores slight stick tilts |
Device Connection/Disconnection Detection
You can detect device state changes, such as plugging and unplugging gamepads.
using UnityEngine;
using UnityEngine.InputSystem;
public class DeviceManager : MonoBehaviour
{
void OnEnable()
{
InputSystem.onDeviceChange += OnDeviceChange;
}
void OnDisable()
{
InputSystem.onDeviceChange -= OnDeviceChange;
}
void OnDeviceChange(InputDevice device, InputDeviceChange change)
{
switch (change)
{
case InputDeviceChange.Added:
Debug.Log($"Device connected: {device.displayName}");
break;
case InputDeviceChange.Removed:
Debug.Log($"Device disconnected: {device.displayName}");
break;
}
}
}
Example use case: Show a pause screen when a gamepad is disconnected, or display a "Controller detected" notification when one is connected.
Common Issues and Troubleshooting
Input Not Responding
- Verify that
inputActions.Enable()is called inOnEnable - Check that the Action Map is enabled
- Verify that Bindings are configured correctly
- If not included in the build: Check the Input Actions Asset settings (see below)
Input Actions Asset Not Included in Build
To include the Input Actions Asset in the build, use one of the following methods:
- Reference via Player Input component - Reference it in a Player Input component attached to a GameObject
- Reference from script - Reference the asset with
[SerializeField] - Register as Addressable - Manage it as an Addressable Asset
Note: The "Preload" checkbox that existed in Input System 1.1 and earlier has been deprecated (Unity 2021+). Reference the asset using one of the methods above.
Movement Doesn't Stop
Register the canceled event as well:
inputActions.Player.Move.performed += OnMove;
inputActions.Player.Move.canceled += OnMove;
Why can you use the same method?: When the
canceledevent fires,context.ReadValue<Vector2>()automatically returnsVector2.zero. Therefore, using the sameOnMovemethod for bothperformedandcanceledcorrectly setsVector2.zerowhen there is no input.
Diagonal Movement is Too Fast
- Set the Composite Binding Mode to "Digital Normalized"
- Or add the "Normalize Vector 2" Processor
Summary
The New Input System has a steeper learning curve, but offers powerful features that make it worthwhile.
- Input Actions for device-independent input handling
- Action Maps for context-sensitive input switching
- Bindings to assign the same Action to multiple devices
- Interactions and Processors for complex input patterns through configuration alone
- C# Class Generation for type-safe implementation
Start with simple movement and jump, then gradually take on more complex features.