[TIL] 유니티 Input System 활용
📕학습 개요
유니티 캠프 19일차.
오늘부터 본격적으로 4주차 개인 프로젝트를 시작했다. 튜터님의 강의에서 워낙 깔끔한 프로젝트가 구현되었다 보니 혼자 할 때도 뭔가 완벽하게 구현하고자 하는 욕심이 생기고, 이 때문에 시간이 너무 많이 소모되는 것 같다.
이번 프로젝트는 한 게임 내 다양한 미니게임이 존재하는 일종의 메타버스 프로젝트 이므로, 각종 미니게임 마다 바뀌는 플레이어의 컨트롤 방식을 어떻게 구현할 지 많은 고민을 했다. 전략 패턴으로 구현해보다가 뭔가 너무 과하다 싶어 튜터님의 도움을 받았는데, Input System 을 사용해보라는 조언을 받았다. 내가 왜 그 생각을 못했을까.
여태 유니티의 인풋 시스템을 사용해 본 적은 있지만, 그냥 단순하게 한 종류의 맵핑만 받아와서 해본게 전부, 다양한 맵핑을 자유롭게 변환하며 컨트롤 방식을 바꾸는 용도로 사용해본 건 처음이었다.
📖학습 내용
Input System 활용
1. 기본 설정 및 구조
- Input Actions Asset (
.inputactions): 프로젝트 내에서 입력을 정의하고 관리하는 중앙 에셋. - Action Maps: 게임 상태나 미니게임별로 입력 세트를 그룹화 (예:
MainMenu,PlayerPlatform,PlayerFlappy). Scene 전환이나 게임 상태 변경 시 활성화/비활성화하여 입력 방식을 전환. - Actions: 개별 입력 동작 정의 (예:
Move,Jump,Look).- Action Type:
Value(지속적인 값),Button(눌림/뗌 상태),Pass Through(모든 변경 전달). - Control Type: 예상되는 값의 타입 (예:
Vector2,Button,Axis,Float).
- Action Type:
- Bindings: 실제 물리적 입력(키, 마우스 버튼, 게임패드 축/버튼 등)을 Action에 연결.
- 마우스 화면 위치 바인딩:
Pointer > Position(Control Type:Vector2).
- 마우스 화면 위치 바인딩:
- Generate C# Class: Input Actions 에셋 Inspector에서 활성화 시, 에셋 구조를 반영하는 C# 클래스 자동 생성. 코드에서 타입 안전하게 Action 및 Map에 접근 가능. 변경 후에는 반드시 “Apply” 클릭.
2. 스크립트에서의 사용법 (Generated C# Class 기반)
-
인스턴스화:
Awake등에서 생성된 클래스의 인스턴스 생성.private PlayerInputSystem playerInputSystem; // PlayerInputSystem은 생성된 클래스 이름 void Awake() { playerInputSystem = new PlayerInputSystem(); } -
Action/Map 참조: 생성된 인스턴스를 통해 Action Map과 Action에 접근.
private InputActionMap platformMap; private InputAction moveAction; private InputAction lookAction; void Awake() { // ... 인스턴스화 ... platformMap = playerInputSystem.PlayerPlatform; // "PlayerPlatform"은 Action Map 이름 moveAction = platformMap.FindAction("Move"); // "Move"는 Action 이름 // 또는 직접 접근: moveAction = playerInputSystem.PlayerPlatform.Move; lookAction = platformMap.FindAction("Look"); } - 활성화/비활성화 (Lifecycle):
OnEnable(): 사용할 Action Map 활성화 (map.Enable()), 개별 Action 활성화 (action.Enable()), 이벤트 구독 (+=).OnDisable(): 이벤트 구독 해제 (-=), Action 비활성화 (action.Disable()), Map 비활성화 (map.Disable()). 리소스 누수 방지를 위해 필수!OnDestroy(): Input System 인스턴스Dispose()(특히DontDestroyOnLoad객체).
-
Action Map 전환: 특정 게임 상태나 Scene에 맞는 Map만 활성화하는 함수 구현.
public void SwitchActionMap(string mapName) { DisableAllActionMaps(); // 기존 맵 모두 비활성화 InputActionMap targetMap = playerInputSystem.asset.FindActionMap(mapName); targetMap?.Enable(); // 새 맵 활성화 } private void DisableAllActionMaps() { foreach (var map in playerInputSystem.asset.actionMaps) { map.Disable(); } } -
개별 Action 활성화 (
action.Enable()):- Action Map이 활성화되어도,
ReadValue()로 폴링할 Action은 명시적으로Enable()해주는 것이 안전하고 명확함 (특히Update에서 지속적으로 값을 읽을 때). - 이벤트 기반 Action은 구독(
+=) 시 암시적으로 처리될 수 있지만, 명시적Enable/Disable이 권장됨.
- Action Map이 활성화되어도,
3. 입력 처리 방식
폴링 (Polling)
Update()또는FixedUpdate()등에서 매 프레임 현재 입력 값을 읽어옴.- 지속적인 입력(이동, 마우스 조준 등) 처리에 적합.
- 사용법:
action.ReadValue<T>()(T는 Control Type과 일치).void Update() { Vector2 moveInput = moveAction.ReadValue<Vector2>(); Vector2 mousePos = lookAction.ReadValue<Vector2>(); // ... 값 사용 ... }
이벤트 기반 (Callbacks)
- 입력 상태 변경(시작, 수행, 취소 등) 시점에 등록된 함수(콜백)를 호출.
- 단발성 입력(점프, 발사, UI 상호작용) 또는 입력 상태 변화 감지에 유용.
-
사용법:
- 구독:
action.performed += CallbackFunction;,action.canceled += CallbackFunction;,action.started += ...(OnEnable에서). - 구독 해제:
action.performed -= CallbackFunction;(OnDisable에서). - 콜백 함수:
InputAction.CallbackContext를 매개변수로 받음. - 콜백 내 값 읽기:
context.ReadValue<T>().
void OnEnable() { jumpAction.performed += OnJump; } void OnDisable() { jumpAction.performed -= OnJump; } void OnJump(InputAction.CallbackContext context) { // 점프 로직 실행 Debug.Log("Jump performed!"); // bool buttonState = context.ReadValueAsButton(); // 버튼 상태 읽기 } void OnMove(InputAction.CallbackContext context) { Vector2 input = context.ReadValue<Vector2>(); // Move 값 읽기 // ... 값 사용 ... } - 구독:
🏁오늘 배운 핵심 내용 정리
- Action Maps 활용 : 필요에 따라
Action Map을 만들어 입력 방식을 구분하고,SwitchActionMap()함수로 필요한 맵만 활성화/비활성화하여 관리한다. - 연속적인 값은 폴링(Polling), 단발성 입력이나 상태 변경 감지는 이벤트로 값을 읽어온다.
- 입력 중단 ->
canceled이벤트로 관리 가능 - 비활성화(OnDisable) 시 이벤트 구독 해제 필수!
댓글남기기