Input System
Input System은 레거시 Input.GetKey 폴링을 대체하는 최신 패키지로 리맵·멀티 디바이스·이벤트 기반 Action을 지원합니다. Action Maps·Bindings·C# 클래스 생성·OnEnable 구독과 리바인딩을 다룹니다. 핵심 개념과 실습을 함께 익힙니다.
상상해 보세요...
구 Input System은 직원이 0.016초마다 전화해 "손님 왔나요?"라고 묻는 방식(폴링)입니다. 신 Input System은 초인종(이벤트)을 달아——눌릴 때만 들립니다. Action Maps는 배정 보드처럼——같은 "Confirm"이 메뉴에선 Navigate Accept, 게임플레이에선 Jump입니다. `if (context == menu)` 스파게티가 없습니다.
개념 자세히
Input Actions Asset은 모든 바인딩을 담는
.inputactions 파일입니다. 구조는
Action Maps(Gameplay, UI, Vehicle…) → 각 Map에
Actions(Move, Jump, Fire…) → 각 Action에
Bindings(키, 스틱, 게임패드 버튼…).
이벤트 기반:
action.started, action.performed, action.canceled에
구독합니다. 값은 context.ReadValue<Vector2>()로 읽습니다.
Update 폴링이 필요 없습니다.
Player Input 컴포넌트: GameObject에 붙여 이벤트를 자동으로 연결합니다. Messages, C# Events, Unity Events를 지원합니다.
런타임 리맵:
action.AddBinding()과
InputActionRebindingExtensions.PerformInteractiveRebinding()으로
Settings 메뉴에서 키바인드를 바꿀 수 있습니다.
다이어그램: Input System 아키텍처
Input Actions Asset (.inputactions)
Actions: Move, Jump, Fire, Interact...
started / performed / canceled events
PlayerController
OnMove(ctx)
UINavigator
OnNavigate(ctx)
VehicleDriver
OnSteer(ctx)
실습 단계
Input System 패키지 설치
Window → Package Manager → Input System → Install. 안내가 나오면 재시작.
Input Actions Asset 만들기
Assets → Create → Input Actions. Action Maps·Actions·키/버튼별 Bindings를 추가합니다.
C# 클래스 생성
.inputactions 선택 → Inspector → "Generate C# Class" 체크 → Apply → Unity가 래퍼 클래스를 만듭니다.
이벤트 구독 / 해제
OnEnable: _actions.Gameplay.Jump.performed += OnJump; OnDisable: 같은 방식으로 해제.
인터랙티브 시뮬레이터
키(또는 아래 버튼)를 누르고 활성 Action Map의 올바른 리스너로 이벤트가 가는 모습을 보세요.
Virtual Input
Event Log
키를 눌러 이벤트를 보세요...
코드 예제
기본생성된 C# 클래스와 이벤트 구독을 사용합니다.
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);
}코드 예제
고급인터랙티브 리바인딩——플레이어가 런타임에 키바인드를 바꿉니다.
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);
// Persist binding overrides
PlayerPrefs.SetString("JumpBinding", jumpAction.action.SaveBindingOverridesAsJson());
})
.Start();
}
}📌 빠른 정리
- ▸컨텍스트에 따라 ActionMaps Enable/Disable (Gameplay ↔ UI)
- ▸OnEnable에서 구독, OnDisable에서 해제
- ▸
performed= 누름;canceled= 뗌 - ▸C# 클래스 생성 → 더 깔끔한 API + IntelliSense
⚠️ 흔한 실수
❌ Action Map에 Enable() 잊음
구독해도 Action이 안 불림——조용한 실패
✅ OnEnable에서 _actions.Gameplay.Enable()
❌ OnDisable에서 Unsubscribe 잊음
메모리 누수——파괴된 객체로 이벤트 호출
✅ OnEnable/OnDisable로 Subscribe/Unsubscribe를 항상 대칭