Input System
Input System package hiện đại của Unity — remap linh hoạt, hỗ trợ nhiều thiết bị, action theo sự kiện — thay thế hoàn toàn API polling Input.GetKey() cũ.
Hãy tưởng tượng...
Input System cũ = nhân viên phải liên tục gọi điện hỏi "Có khách chưa?" mỗi 0.016 giây (polling). Input System mới = lắp chuông cửa (event) — chỉ nhận thông báo khi có khách nhấn chuông. Ngoài ra, Action Maps giống bảng điều phối — cùng nút "Confirm" nhưng trong menu → Navigate Accept, trong game → Jump. Không cần viết if context == menu.
Khái niệm chi tiết
Input Actions Asset: file
.inputactions cấu hình toàn bộ binding. Tổ chức theo
Action Maps (Gameplay, UI, Vehicle…) → mỗi Map có
các Actions (Move, Jump, Fire…) → mỗi Action có
Bindings (phím, joystick, gamepad button…).
Event-driven: Subscribe vào
action.started, action.performed, action.canceled. Gọi
context.ReadValue<Vector2>() để lấy giá trị. Không cần polling trong
Update.
Player Input component: Gắn vào GameObject → tự tạo Player Input component → subscribe events tự động. Hỗ trợ Message, C# Events, hoặc Unity Events.
Remapping tại runtime:
action.AddBinding(),
InputActionRebindingExtensions.PerformInteractiveRebinding() cho phép người chơi
tự đổi keybind trong Settings menu.
Sơ đồ: Input System Architecture
Input Actions Asset (.inputactions)
Actions: Move, Jump, Fire, Interact...
started / performed / canceled events
PlayerController
OnMove(ctx)
UINavigator
OnNavigate(ctx)
VehicleDriver
OnSteer(ctx)
Hướng dẫn thực hành
Cài Input System package
Window → Package Manager → Input System → Install. Khởi động lại khi được hỏi.
Tạo Input Actions Asset
Assets → Create → Input Actions. Thêm Action Maps, Actions, và Bindings cho từng phím/button.
Generate C# class
Chọn .inputactions file → Inspector → tick "Generate C# Class" → Apply → Unity tạo class wrapper.
Subscribe/Unsubscribe events
OnEnable: _actions.Gameplay.Jump.performed += OnJump; OnDisable: unsubscribe tương tự.
Trình mô phỏng tương tác
Nhấn các phím (hoặc click button bên dưới) và xem event được gọi đến đúng listener theo Action Map.
Virtual Input
Event Log
Nhấn phím để xem events...
Ví dụ Code
Cơ bảnDùng generated C# class với event subscription.
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
private GameControls _actions; // Generated C# class
private Rigidbody _rb;
private Vector2 _moveInput;
void Awake()
{
_rb = GetComponent<Rigidbody>();
_actions = new GameControls();
}
void OnEnable()
{
_actions.Gameplay.Enable();
_actions.Gameplay.Move.performed += OnMove;
_actions.Gameplay.Move.canceled += OnMove;
_actions.Gameplay.Jump.performed += OnJump;
}
void OnDisable()
{
_actions.Gameplay.Move.performed -= OnMove;
_actions.Gameplay.Move.canceled -= OnMove;
_actions.Gameplay.Jump.performed -= OnJump;
_actions.Gameplay.Disable();
}
void OnMove(InputAction.CallbackContext ctx)
=> _moveInput = ctx.ReadValue<Vector2>();
void OnJump(InputAction.CallbackContext ctx)
=> _rb.AddForce(Vector3.up * 5f, ForceMode.Impulse);
void FixedUpdate()
=> _rb.velocity = new Vector3(_moveInput.x * 5f, _rb.velocity.y, _moveInput.y * 5f);
}Ví dụ Code
Nâng caoInteractive Rebinding — cho phép người chơi đổi keybind tại runtime.
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
public class KeyRebinder : MonoBehaviour
{
[SerializeField] private InputActionReference jumpAction;
[SerializeField] private TextMeshProUGUI bindingLabel;
private InputActionRebindingExtensions.RebindingOperation _rebindOp;
public void StartRebind()
{
jumpAction.action.Disable();
bindingLabel.text = "Press any key...";
_rebindOp = jumpAction.action
.PerformInteractiveRebinding()
.WithControlsExcluding("Mouse")
.OnMatchWaitForAnother(0.1f)
.OnComplete(op => {
op.Dispose();
jumpAction.action.Enable();
bindingLabel.text = InputControlPath.ToHumanReadableString(
jumpAction.action.bindings[0].effectivePath);
// Lưu binding string vào PlayerPrefs để persist
PlayerPrefs.SetString("JumpBinding", jumpAction.action.SaveBindingOverridesAsJson());
})
.Start();
}
}📌 Ghi nhớ nhanh
- ▸Enable/Disable ActionMap theo context (Gameplay ↔ UI)
- ▸Subscribe trong OnEnable, Unsubscribe trong OnDisable
- ▸
performed= phím/button được nhấn;canceled= thả - ▸Generate C# class → gọn hơn, IntelliSense support
⚠️ Lỗi thường gặp
❌ Quên Enable() Action Map
Actions không kích hoạt dù đã subscribe — im lặng, không báo lỗi
✅ _actions.Gameplay.Enable() trong OnEnable
❌ Quên Unsubscribe trong OnDisable
Memory leak — event gọi vào object đã bị destroy
✅ Luôn mirror Subscribe/Unsubscribe theo OnEnable/OnDisable