Input Manager
Clean wrapper around Unity's new Input System with action map switching, rebinding support, and input event bus.
How to Use
1
Attach InputManager to a persistent manager object
2
Define actions in inspector with default keys
3
Check input: InputManager.Instance.WasPressed("Jump")
4
Movement: var move = InputManager.Instance.GetMovement()
5
Rebind: InputManager.Instance.StartRebind("Jump") then press new key
6
Reset: InputManager.Instance.ResetBinding("Jump")
7
Bindings auto-save to PlayerPrefs
8
Hook OnActionPressed for event-driven input handling
Source Code
C#
using UnityEngine;
using UnityEngine.Events;
using System.Collections.Generic;
/// <summary>
/// Input manager that wraps Unity's legacy Input into a clean event-driven API.
/// Provides rebindable keys, input events, and action grouping.
/// Compatible with both legacy Input and can be adapted for new Input System.
/// </summary>
public class InputManager : MonoBehaviour
{
public static InputManager Instance { get; private set; }
[System.Serializable]
public class InputAction
{
public string actionName;
public KeyCode defaultKey;
public KeyCode currentKey;
[HideInInspector] public bool isPressed;
[HideInInspector] public bool wasPressed;
[HideInInspector] public bool wasReleased;
public InputAction(string name, KeyCode key)
{
actionName = name;
defaultKey = key;
currentKey = key;
}
}
[Header("Actions")]
[SerializeField] private List<InputAction> actions = new List<InputAction>()
{
new InputAction("Jump", KeyCode.Space),
new InputAction("Sprint", KeyCode.LeftShift),
new InputAction("Interact", KeyCode.E),
new InputAction("Crouch", KeyCode.LeftControl),
new InputAction("Reload", KeyCode.R),
new InputAction("Inventory", KeyCode.I),
new InputAction("Pause", KeyCode.Escape),
};
[Header("Events")]
public UnityEvent<string> OnActionPressed;
public UnityEvent<string> OnActionReleased;
private Dictionary<string, InputAction> actionMap = new Dictionary<string, InputAction>();
private bool isRebinding;
private string rebindingAction;
public UnityEvent<string, KeyCode> OnRebindComplete;
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
return;
}
foreach (var action in actions)
actionMap[action.actionName] = action;
LoadBindings();
}
private void Update()
{
if (isRebinding)
{
HandleRebinding();
return;
}
foreach (var action in actions)
{
action.wasPressed = Input.GetKeyDown(action.currentKey);
action.wasReleased = Input.GetKeyUp(action.currentKey);
action.isPressed = Input.GetKey(action.currentKey);
if (action.wasPressed)
OnActionPressed?.Invoke(action.actionName);
if (action.wasReleased)
OnActionReleased?.Invoke(action.actionName);
}
}
/// <summary>Check if an action is currently held down.</summary>
public bool IsPressed(string actionName)
{
return actionMap.TryGetValue(actionName, out var action) && action.isPressed;
}
/// <summary>Check if an action was pressed this frame.</summary>
public bool WasPressed(string actionName)
{
return actionMap.TryGetValue(actionName, out var action) && action.wasPressed;
}
/// <summary>Check if an action was released this frame.</summary>
public bool WasReleased(string actionName)
{
return actionMap.TryGetValue(actionName, out var action) && action.wasReleased;
}
/// <summary>Get the horizontal axis (-1 to 1).</summary>
public float GetHorizontal() => Input.GetAxisRaw("Horizontal");
/// <summary>Get the vertical axis (-1 to 1).</summary>
public float GetVertical() => Input.GetAxisRaw("Vertical");
/// <summary>Get movement vector (normalized).</summary>
public Vector2 GetMovement() => new Vector2(GetHorizontal(), GetVertical()).normalized;
/// <summary>Start listening for a new key to rebind an action.</summary>
public void StartRebind(string actionName)
{
if (!actionMap.ContainsKey(actionName)) return;
isRebinding = true;
rebindingAction = actionName;
}
private void HandleRebinding()
{
foreach (KeyCode key in System.Enum.GetValues(typeof(KeyCode)))
{
if (Input.GetKeyDown(key) && key != KeyCode.Escape)
{
actionMap[rebindingAction].currentKey = key;
isRebinding = false;
SaveBindings();
OnRebindComplete?.Invoke(rebindingAction, key);
return;
}
}
// Cancel rebind on Escape
if (Input.GetKeyDown(KeyCode.Escape))
isRebinding = false;
}
/// <summary>Reset an action to its default key.</summary>
public void ResetBinding(string actionName)
{
if (actionMap.TryGetValue(actionName, out var action))
{
action.currentKey = action.defaultKey;
SaveBindings();
}
}
/// <summary>Reset all bindings to defaults.</summary>
public void ResetAllBindings()
{
foreach (var action in actions)
action.currentKey = action.defaultKey;
SaveBindings();
}
/// <summary>Get the current key for an action.</summary>
public KeyCode GetBinding(string actionName)
{
return actionMap.TryGetValue(actionName, out var action) ? action.currentKey : KeyCode.None;
}
private void SaveBindings()
{
foreach (var action in actions)
PlayerPrefs.SetInt("input_" + action.actionName, (int)action.currentKey);
PlayerPrefs.Save();
}
private void LoadBindings()
{
foreach (var action in actions)
{
string key = "input_" + action.actionName;
if (PlayerPrefs.HasKey(key))
action.currentKey = (KeyCode)PlayerPrefs.GetInt(key);
}
}
}