TIL_039: 언리얼 입력 처리 시스템

김펭귄·2025년 9월 29일

Today What I Learned (TIL)

목록 보기
39/139

오늘 학습 키워드

  • GameMode, Pawn, PlayerController

  • Enhanced Input System

  • 코드

  • 게임에서의 입력 처리 시퀀스

1. GameMode, Pawn, PlayerController

  • 먼저 게임에 필수적인 3가지 구성요소에 대해 알아보자
    (GameMode, Pawn, PlayerController)

GameMode

  • 게임의 전반적인 규칙과 흐름을 총괄 관리하는, 일종의 컨트롤 타워 역할을 하는 클래스

  • 게임이 시작했는지, 끝났는지, 점수 계산, 난이도 등을 규칙을 정의하고 관리

  • 또한, 플레이어에게 어떤 Pawn(Character)을 스폰해줄지, 어떤 PlayerController를 사용할지에 대해서도 관리

Pawn (Character)

  • 게임 캐릭터, 플레이어 가능한 객체

  • Pawn은 플레이어 혹은 AI가 “소유( Possess )”하여 조종할 수 있는 가장 기본적인 형태

  • Character는 UCharacterMovementComponent를 가져, 사람 캐릭터에 적합한 Playable 객체

  • 하지만 PawnCharacter 혼자서는 어떠한 입력값에도 반응하지 못 함. 인형처럼

  • 내부에 이동, 회전, 점프 등 다양한 로직들이 함수로 구현만 되어 있지 사용자의 Inupt(키보드, 마우스)에 반응하지 못 함

PlayerController

  • 이를 PlayerController가 해줌

  • GameMode가 생성하여 Pawn 또는 Character에 빙의시켜 소유하도록 함

  • 사용자마다 하나씩 존재하여 각 플레이어 캐릭터를 소유, 제어

  • 게임 중에 받은 입력값을 먼저 인식하고, 플레이어 캐릭터가 동작할 수 있도록 해줌

  • 따라서, 싱글게임의 경우 GameMode, PlayerController, Pawn(character)은 1개씩 존재
  • 멀티의 경우 GameMode는 서버에만 1개 존재, PlayerController, Pawn(character)은 플레이어의 수만큼 존재.

2. Enhanced Input System

  • 언리얼 엔진에서 기존에 사용하던 Input System은 정말 단순하게 특정키와 특정 함수를 바인딩하여 사용하였음

  • 하지만 현재 게임은 같은 키를 입력하여도 게임 상황에 따라 동작 방식이 달라짐

    • 방향키를 눌렀을 때, 게임에서는 플레이어가 이동하지만, 옵션에서는 선택지를 이동하게 됨
    • 마찬가지로 똑같은 방향키로도 평소엔 걷다가, 차를 탔을 경우 운전을 하게 됨
  • 위 상황처럼 이제는 Enhanced Input System을 사용하여 입력값을 더 유연하게 관리할 수 있음

  • Input ActionInput Mapping Context를 이용

Input Action

  • 캐릭터의 이동, 점프, 발사, 줌 등과 같이 특정 동작을 추상화한 단위

  • 이동을 담당하는 IA_Move, 점프를 담당하는 IA_Jump, 카메라 회전을 담당하는 IA_Look

  • 입력 키와 상관 없이 그냥 "이동", "점프" 등 동작을 중심으로 어떤 형태의 입력을 받을지 정의 (bool, Axis1D, Axis2D, Axis3D)

Input Mapping Context

  • 사용할 Input Action들을 하나의 Context로 그룹화하고, 각 IA들을 실제 입력키에 매핑
  • 여러 IMC를 우선순위에 따라 입력 처리를 다르게 할 수 있다. 예를 들어, 평소에는 '이동' 컨텍스트, 인벤토리 창을 열면 '인벤토리' 컨텍스트가 더 높은 우선순위로 적용되어 같은 키를 다른 동작에 쓸 수 있다
  • 런타임 중에 컨텍스트를 추가하거나 제거할 수 있어, 게임 상황에 따라 입력 방식을 유연하게 바꿀 수 있다

3. 구현 코드

GameMode

헤더

cpp

  • DefaultPawnClass를 통해 어떤 객체를 플레이어 캐릭터로 사용할지 설정
  • PlayerControllerClass를 통해 어떤 객체를 플레이어 컨트롤러로 사용할지 설정

PlayerController

헤더

  • IMCIA들을 리플렉션시스템에 등록하여, 에디터에서 생성한 IMC와 IA들을 컨트롤러에 연결할 수 있게 설정

cpp

  • LocalPlayer : 현재 PlayerController가 관리하는 Local Player를 반환

  • GetSubsystem<UEnhancedInputLocalPlayerSubsystem>() : 해당 Local Player에 부착된 Enhanced Input Subsystem을 반환

  • AddMappingContext()

    • IMC를 Subsystem에 추가하여 입력 매핑을 활성화
    • 0 : 우선순위. 낮을수록 높은 우선순위
    • 이 함수를 여러 번 호출해 여러 IMC를 활성화 가능
  • 컨트롤러에서 IMC를 동적으로 장착했다가 제거했다가 하며, 유연한 Input 처리를 가능하게 해줌

  • 키마로 게임하다가 패드로 게임한다든지, 게임하다가 UI로 들어가 설정을 조작한다든지 이런 상황을 GameMode가 인지하여 컨트롤러에게 알려주고 컨트롤러가 그에 맞게 IMC를 설정

Character

헤더

  • FInputActionValue : Enhanced Input에서 입력값(축 이동값, 마우스 이동량 등)을 전달할 때 사용하는 구조체로, IA에서 설정한 Value Type으로 받아 사용

  • UFUNCTION() : 입력 바인딩 함수는 리플렉션 시스템과 연동되어야 함

  • bool형식의 IA는 키가 눌렸을 때와 키가 떼졌을 때의 동작을 따로 만들어줘야하므로 Start~, Stop~ 처럼 함수 2개 만들어줌
    (shift누르고 있을 때는 속도 빠르게 설정, 때면은 속도 다시 정상으로 만들어주기)

cpp

  • SetupPlayerInputComponent : 캐릭터와 컨트롤러가 연동(빙의)되었을 때 호출되어, IA와 동작할 함수를 binding해줌

  • BindAction :

    • 첫 번째 인자: Binding할 IA
    • 두 번째 인자: 액션이 발생하는 트리거 이벤트 (Triggered, Ongoing, Completed 등)
    • 세 번째 인자 : 액션 발생 시 실행할 객체(this)
    • 네 번째 인자: 액션 발생 시 실행할 함수 포인터 (함수포인터를 다른 함수로 넘겨줘야하므로 &객체::함수이름 형식의 문법 사용)

  • bool형의 "달리기"는 누르고 있는 상태는 Triggered, 키를 뗐을 때는 Completed를 이용

  • value : IA_MOVE에서 2D값으로 받는다고 설정했으므로, value값에서 FVector2D값을 추출하여 사용

  • 이렇게 어떤 키가 눌렸는지 상관 없이, 입력값만을 이용해 동작할 함수를 구현하면 된다

4. 게임에서의 입력 처리 시퀀스

  1. 사용자가 게임 도중 키를 입력

  2. 어떤 입력을 하였는지(w입력) 입력 자체를 언리얼 엔진에서 컨트롤러에게 전달

  3. 하지만 컨트롤러는 이 입력을 해석하지 못해, 무엇을 해야하는지 모름. 정말 어떤 입력이 들어왔는지만 앎

  4. 그래서 컨트롤러는 Enhanced Input System에게 이 입력이 무슨 뜻인지 물어봄

  5. 그럼 Enhanced Input System은 등록되어 있는 IMC를 기반으로 이 입력을 IA로 변환해서 발동을 시킴(Triggered)

  6. 이전에 컨트롤러와 캐릭터가 연동되었을 때, IA와 호출할 함수가 Bind되었으므로, IA가 발동되거나 종료된거에 따라 Bind된 함수가 호출되면서 입력이 처리가 된다

profile
반갑습니다

0개의 댓글