본문 바로가기

Pawn, Character, Controller 이해

Controller가 Pawn을 Possess하는 흐름과 Character의 이동·충돌·애니메이션 확장 구조를 구분합니다.

플레이어가 걸어 다니다가 차에 올라타 운전하는 게임을 생각해 봅시다. 플레이어의 입력은 그대로인데, 조종하는 대상은 사람에서 차로 바뀝니다. 만약 입력 처리와 몸체의 동작이 한 클래스에 섞여 있다면, 차에 탈 때마다 입력 코드를 옮기거나 복사해야 합니다. 언리얼은 이 문제를 "조종하는 쪽"과 "조종당하는 몸체"를 나누는 방식으로 풉니다.

게임 루프와 주요 클래스 구조에서 각 클래스의 큰 역할을 보았으니, 이 글에서는 조종의 중심인 APawn, ACharacter, AController를 자세히 살펴봅니다. 몸체인 폰과 캐릭터가 무엇을 제공하는지, 두뇌인 컨트롤러가 무엇을 맡는지, 그리고 빙의(Possess)를 바꿀 때 무엇이 바뀌고 무엇이 그대로인지를 정리합니다.


APawn: 조종할 수 있는 몸체

APawn은 3D 월드에 존재하며 AController가 빙의해 조종할 수 있는 AActor의 한 종류입니다. 폰은 기본적으로 눈에 보이는 모습이나 복잡한 이동 로직을 가지고 있지 않습니다. 대신 컨트롤러에게서 명령을 받아 움직이거나 행동하는 대리인 역할을 합니다.

폰은 APlayerController나 AAIController가 빙의할 수 있습니다. 빙의는 조종 연결일 뿐 움직이기 위한 필수 조건은 아니어서, 빙의되지 않은 폰도 물리나 직접 작성한 로직으로 움직일 수 있습니다. 또 AActor를 상속하므로 월드 안에서 위치, 회전, 스케일을 가집니다.

APawn 자체에는 메시도 이동 로직도 없지만, 컴포넌트를 더해 기능을 넓힐 수 있습니다. 예를 들어 UStaticMeshComponent를 더해 모양을 주고, UFloatingPawnMovement 같은 이동 컴포넌트를 붙여 움직임을 구현합니다. 입력도 보통은 폰이 직접 처리하기보다 자신을 조종하는 컨트롤러에게서 명령을 받지만, 필요하다면 폰이 직접 입력을 바인딩해 처리할 수도 있습니다.

그래서 APawn은 사람 형태가 아닌 조종 대상에 알맞습니다. 차량, 비행기, 드론, 탱크처럼 캐릭터의 보행 이동과 다른 이동 방식을 직접 만들 때 APawn을 상속하고, 단순한 움직임이나 상호작용만 하는 AI 대상에도 씁니다.


ACharacter: 사람형 이동을 갖춘 폰

ACharacter는 APawn을 상속한 특화된 폰입니다. 사람 형태의 플레이어 캐릭터나 AI 캐릭터를 만들기 좋게 설계되어 있어, 폰의 기능 위에 이동, 충돌, 애니메이션 연동에 필요한 기본 컴포넌트를 갖추고 있습니다.

첫 번째는 루트 컴포넌트로 자동 포함되는 UCapsuleComponent입니다. 캐릭터의 충돌 영역을 캡슐 모양으로 정하며, 캐릭터가 이동할 때 주로 쓰는 충돌 형상입니다. 두 번째는 USkeletalMeshComponent로, 애니메이션할 수 있는 3D 모델인 스켈레탈 메시를 그립니다. 캐릭터의 눈에 보이는 부분을 맡고, 애니메이션 블루프린트와 연결되어 복잡한 애니메이션을 재생합니다.

세 번째이자 가장 중요한 것은 UCharacterMovementComponent입니다. 중력, 점프, 걷기, 달리기, 웅크리기, 낙하 같은 이동 로직이 미리 구현되어 있어 설정을 조정하고 함수를 호출하는 것만으로 다양한 움직임을 만들 수 있습니다. 또 네트워크 멀티플레이어에서 이동을 동기화하는 기능까지 갖추고 있어, 여러 클라이언트에서 캐릭터 이동을 맞추는 일을 직접 만들지 않아도 됩니다.

그래서 FPS나 TPS 게임의 주인공, RPG의 캐릭터처럼 사람 형태의 복잡한 움직임이 필요한 대부분의 플레이어 캐릭터에는 ACharacter를 씁니다. NPC나 몬스터처럼 UCharacterMovementComponent의 이동 로직이 필요한 사람형 AI 캐릭터에도 마찬가지입니다.


AController: 폰을 움직이는 두뇌

AController는 APawn이나 ACharacter에 빙의해 조종하는 클래스입니다. 컨트롤러 자체는 월드에 보이지 않으며, 폰과 캐릭터가 몸이라면 컨트롤러는 그 몸을 움직이는 두뇌에 해당합니다. 컨트롤러는 크게 두 가지 파생 클래스로 나뉩니다.

APlayerController: 플레이어의 두뇌

APlayerController는 플레이어의 키보드, 마우스, 게임패드 입력을 받아 폰이나 캐릭터를 조종하고 게임 월드와 상호작용하게 합니다. 플레이어의 HUD(Head-Up Display) 표시, 인벤토리, 설정처럼 플레이어마다 다른 일도 함께 관리합니다.

멀티플레이어 게임에 접속한 플레이어는 각자 자신의 APlayerController 인스턴스를 가집니다. 이 인스턴스는 서버와 그 플레이어의 클라이언트에 존재하며, 입력 처리와 명령 전달을 맡습니다. UI 위젯을 만들고 관리하거나 마우스 커서 표시를 제어하는 일도 여기서 합니다.

Possess(APawn* InPawn) 함수로 특정 폰에 빙의해 조종을 시작하고, UnPossess()로 조종을 해제합니다. 그래서 플레이어의 입력과 캐릭터 조작, 플레이어 고유의 데이터 관리, 플레이어에게 보이는 HUD와 메뉴, 그리고 클라이언트와 서버 사이의 원격 프로시저 호출(RPC)을 시작하는 지점으로 APlayerController를 씁니다.

AAIController: AI의 두뇌

AAIController는 AI의 로직을 처리하고, 그 AI가 조종하는 폰이나 캐릭터를 제어하는 클래스입니다. AI 조종을 컨트롤러로 분리하고 싶을 때 쓰며, 모든 자동 동작이 꼭 이 클래스를 거쳐야 하는 것은 아닙니다.

AAIController는 언리얼의 AI 시스템인 행동 트리(Behavior Tree)와 블랙보드(Blackboard)를 실행해 복잡한 AI 로직을 만듭니다. UAIPerceptionComponent 같은 지각 컴포넌트로 시각이나 청각 같은 환경 정보를 받아들여 행동을 정하고, 내비게이션 메시로 이동할 수 있는 경로를 찾아 폰에게 이동 명령을 내립니다. 적, NPC, 아군 AI처럼 컴퓨터가 조종하는 캐릭터의 행동 로직을 만들 때 씁니다.


빙의를 바꾸면 무엇이 바뀌는가

하나의 폰은 한 번에 하나의 컨트롤러에게만 빙의됩니다. 네트워크 게임에서 Possess는 권한(authority)을 가진 쪽, 보통 서버에서 실행하고, 로컬 UI와 입력은 그 로컬 플레이어의 실행 환경에서 처리합니다. 또 게임 도중에 스폰한 폰은 컨트롤러에게 자동으로 빙의되지 않으므로, 필요하면 직접 Possess를 호출해야 합니다.

빙의 연결을 바꾸어도 객체 수명은 별개입니다

기존 C/A/B에서 C→A 제어를 C→B로 바꾸는 실제 관계 전이다. A/B 생성·파괴나 소지품 3개 이전은 자동 추가하지 않는다.

UNREAL C++ · CH3-1

빙의 연결을 바꾸어도 객체 수명은 별개입니다

Possess·UnPossess는 Controller와 Pawn의 제어 연결을 바꿉니다. 생성·파괴·상태 이전까지 자동으로 수행하는 동작은 아닙니다.

전환 전: C가 기존 A를 제어합니다.

기존 세 객체의 빙의 A같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn AC가 제어Pawn B제어자 없음제어 연결같은 세 객체 · 생성·파괴·소지품 복사 아님
기존 세 객체의 빙의 A같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn AC가 제어Pawn B제어자 없음생성·파괴·복사 별도다른 제어자 개입 없음

전환 후: 같은 C가 기존 B를 제어합니다. 세 객체는 그대로 있습니다.

기존 세 객체의 빙의 B같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn A제어 연결 해제Pawn BC가 제어제어 연결같은 세 객체 · 생성·파괴·소지품 복사 아님
기존 세 객체의 빙의 B같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn A제어 연결 해제Pawn BC가 제어생성·파괴·복사 별도다른 제어자 개입 없음
빙의 변경과 객체 수명은 별개다
동작바뀌는 연결자동으로 하지 않는 일
Possess권한 측 Controller가 제어할 Pawn을 선택Pawn이나 이동 컴포넌트를 새로 만드는 작업
UnPossess현재 Controller와 Pawn의 제어 연결 해제두 객체를 모두 파괴하거나 Pawn의 모든 움직임 정지
다른 Pawn으로 전환같은 Controller가 다른 몸체를 제어하도록 변경기존 Pawn의 상태·소지품을 새 Pawn으로 복사
Possess
바뀌는 연결: 권한 측 Controller가 제어할 Pawn을 선택
자동으로 하지 않는 일: Pawn이나 이동 컴포넌트를 새로 만드는 작업
UnPossess
바뀌는 연결: 현재 Controller와 Pawn의 제어 연결 해제
자동으로 하지 않는 일: 두 객체를 모두 파괴하거나 Pawn의 모든 움직임 정지
다른 Pawn으로 전환
바뀌는 연결: 같은 Controller가 다른 몸체를 제어하도록 변경
자동으로 하지 않는 일: 기존 Pawn의 상태·소지품을 새 Pawn으로 복사

GetPawn()과 GetController()가 의도한 상대인지 확인합니다. Controller의 로컬 제어 상태, PlayerState의 공유 상태, Pawn의 몸체 상태를 게임의 수명 정책에 맞춰 나눕니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.
관계도의 보충 설명
원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명같은 Controller C와 기존 PawnA/B의 두 시점을 별도로 표현한다. 전환 전 C→A, 성공한 전환 후 C→B이며 선은 제어 관계 하나다. 생성·파괴·몸체 소지품 복사는 포함하지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
기존 Possess

C가 PawnA를 제어한다.

  • Controller: C
  • 제어 대상: A
  • 제어 관계와 Pawn의 생성·파괴는 별개다.
대상 변경

제어 관계를 PawnB로 바꾼다.

  • 이전: C→A
  • 새 관계: C→B
  • 소지품을 자동으로 이전하거나 A를 자동 파괴하는 단계가 아니다.
현재 상태

C의 현재 Pawn은 B이며 A/B는 독립 객체다.

  • 현재 Pawn: B
  • 아이템 이전: 자동 없음
  • 제어 변화만으로 게임 데이터 이전을 추정하지 않는다.

빙의 연결을 바꾸어도 객체 수명은 별개입니다

기존 C/A/B에서 C→A 제어를 C→B로 바꾸는 실제 관계 전이다. A/B 생성·파괴나 소지품 3개 이전은 자동 추가하지 않는다.

UNREAL C++ · CH3-1

빙의 연결을 바꾸어도 객체 수명은 별개입니다

Possess·UnPossess는 Controller와 Pawn의 제어 연결을 바꿉니다. 생성·파괴·상태 이전까지 자동으로 수행하는 동작은 아닙니다.

전환 전: C가 기존 A를 제어합니다.

기존 세 객체의 빙의 A같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn AC가 제어Pawn B제어자 없음제어 연결같은 세 객체 · 생성·파괴·소지품 복사 아님
기존 세 객체의 빙의 A같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn AC가 제어Pawn B제어자 없음생성·파괴·복사 별도다른 제어자 개입 없음

전환 후: 같은 C가 기존 B를 제어합니다. 세 객체는 그대로 있습니다.

기존 세 객체의 빙의 B같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn A제어 연결 해제Pawn BC가 제어제어 연결같은 세 객체 · 생성·파괴·소지품 복사 아님
기존 세 객체의 빙의 B같은ControllerC와기존PawnA/B의두시점을별도표현한다.전환전C→A,성공한전환후C→B이며선은제어관계하나이다.생성·파괴·몸체소지품복사는포함하지않는다.Controller C같은 제어 주체Pawn A제어 연결 해제Pawn BC가 제어생성·파괴·복사 별도다른 제어자 개입 없음
빙의 변경과 객체 수명은 별개다
동작바뀌는 연결자동으로 하지 않는 일
Possess권한 측 Controller가 제어할 Pawn을 선택Pawn이나 이동 컴포넌트를 새로 만드는 작업
UnPossess현재 Controller와 Pawn의 제어 연결 해제두 객체를 모두 파괴하거나 Pawn의 모든 움직임 정지
다른 Pawn으로 전환같은 Controller가 다른 몸체를 제어하도록 변경기존 Pawn의 상태·소지품을 새 Pawn으로 복사
Possess
바뀌는 연결: 권한 측 Controller가 제어할 Pawn을 선택
자동으로 하지 않는 일: Pawn이나 이동 컴포넌트를 새로 만드는 작업
UnPossess
바뀌는 연결: 현재 Controller와 Pawn의 제어 연결 해제
자동으로 하지 않는 일: 두 객체를 모두 파괴하거나 Pawn의 모든 움직임 정지
다른 Pawn으로 전환
바뀌는 연결: 같은 Controller가 다른 몸체를 제어하도록 변경
자동으로 하지 않는 일: 기존 Pawn의 상태·소지품을 새 Pawn으로 복사

GetPawn()과 GetController()가 의도한 상대인지 확인합니다. Controller의 로컬 제어 상태, PlayerState의 공유 상태, Pawn의 몸체 상태를 게임의 수명 정책에 맞춰 나눕니다.

이 예의 조건

  • 본문과 원 도표에 제시된 사례의 입력·조건을 사용합니다. 설명용 수치나 독립 비교 경로는 각 단계에 표시합니다.
  • 현재 상태·값과 전환 근거의 위치는 모든 단계에서 같습니다. 조건이 맞지 않거나 실행되지 않은 경로를 성공한 동작으로 해석하지 않습니다.

관계도의 보충 설명

원 도표의 제목·노드·관계·조건·주석
범위원문
관계·조건 설명같은 Controller C와 기존 PawnA/B의 두 시점을 별도로 표현한다. 전환 전 C→A, 성공한 전환 후 C→B이며 선은 제어 관계 하나다. 생성·파괴·몸체 소지품 복사는 포함하지 않는다.
예의 값과 변화
관찰·상황값·보충 정보변화·이유
기존 Possess

C가 PawnA를 제어한다.

  • Controller: C
  • 제어 대상: A
  • 제어 관계와 Pawn의 생성·파괴는 별개다.
대상 변경

제어 관계를 PawnB로 바꾼다.

  • 이전: C→A
  • 새 관계: C→B
  • 소지품을 자동으로 이전하거나 A를 자동 파괴하는 단계가 아니다.
현재 상태

C의 현재 Pawn은 B이며 A/B는 독립 객체다.

  • 현재 Pawn: B
  • 아이템 이전: 자동 없음
  • 제어 변화만으로 게임 데이터 이전을 추정하지 않는다.

위 그림은 같은 컨트롤러 C와 기존 폰 A, B의 두 시점을 나란히 보여 줍니다. 전환 전에는 C가 A를 조종하고 B에는 조종자가 없습니다. 전환이 성공한 뒤에는 같은 C가 B를 조종하고, 다른 조종자가 끼어들지 않았다면 A와의 연결은 해제됩니다. 그림의 선은 조종 관계 하나만 나타내며, 세 객체는 전환 전후로 그대로 있습니다.

그림의 표는 각 동작이 바꾸는 연결과 자동으로 하지 않는 일을 정리합니다. Possess는 권한 쪽 컨트롤러가 조종할 폰을 고르는 일일 뿐 폰이나 이동 컴포넌트를 새로 만들지 않습니다. UnPossess는 현재 컨트롤러와 폰의 연결을 끊을 뿐 두 객체를 파괴하거나 폰의 모든 움직임을 멈추지 않습니다. 다른 폰으로 전환하는 것도 같은 컨트롤러가 다른 몸체를 조종하게 바꾸는 것이지, 기존 폰의 상태나 소지품을 새 폰으로 복사하는 일이 아닙니다. 단계 그림도 C가 A를 조종하는 상태에서 대상을 B로 바꾸고, 마지막에 A와 B가 각자 독립된 객체로 남는 과정을 차례로 보여 줍니다.

연결이 제대로 바뀌었는지는 컨트롤러의 GetPawn()과 폰의 GetController()가 의도한 상대를 가리키는지로 확인합니다. 그림 아래의 설명처럼 컨트롤러의 로컬 조종 상태, PlayerState의 공유 상태, 폰의 몸체 상태는 게임의 수명 정책에 맞춰 나눠 둡니다. 점수처럼 다른 클라이언트도 알아야 하는 플레이어 상태는 폰이 아니라 PlayerState 같은 곳에 둡니다.

구체적으로 따라가 봅시다. 권한 쪽의 컨트롤러 C가 기존 폰 A를 조종하고 있고, 기존 폰 B는 아직 조종자가 없습니다. 게임의 전환 처리가 성공해 C가 B를 Possess하면, C의 GetPawn()은 B를, B의 GetController()는 C를 가리킵니다. 다른 조종자가 끼어들지 않았다면 A의 조종 연결은 해제됩니다. 이 과정에서 A와 B를 새로 만들거나 파괴한 것은 아니며, A의 몸체에 보관한 소지품 3개가 B로 자동 복사되지도 않습니다. 상태를 어디에 두고 언제 옮길지는 따로 정해야 하는 게임 규칙입니다.

더 깊이: 스폰한 폰이 저절로 빙의되는 경우

폰에는 자동 빙의를 정하는 속성이 두 개 있습니다. AutoPossessPlayer는 레벨이 시작되거나 폰이 스폰될 때 어느 플레이어 컨트롤러가 이 폰을 자동으로 빙의할지 정합니다. AutoPossessAI는 폰이 언제 AI 컨트롤러를 만들어 빙의되는지 정하며, 값은 네 가지입니다. Disabled는 자동 빙의를 하지 않고, PlacedInWorld는 레벨에 배치된 폰만, Spawned는 월드를 불러온 뒤에 스폰된 폰만, PlacedInWorldOrSpawned는 만들어지는 모든 폰을 AI 컨트롤러가 빙의하게 합니다. 이때 만들어지는 컨트롤러의 클래스는 AIControllerClass가 정합니다.

그래서 앞에서 '게임 도중에 스폰한 폰은 자동으로 빙의되지 않는다'고 한 것은 이 속성들이 그 경우를 켜 두지 않았을 때의 이야기입니다. 실행 중에 스폰한 적 캐릭터가 움직이지 않는다면, AutoPossessAI가 스폰된 폰을 포함하는 값인지와 AIControllerClass가 지정되어 있는지를 먼저 확인합니다. 자동 빙의를 켜지 않고 필요한 순간에만 AI를 붙이고 싶다면 폰의 SpawnDefaultController()를 호출해 기본 컨트롤러를 만들고 빙의시킬 수 있습니다.

빙의가 이루어지면 폰의 PossessedBy가 호출되는데, API 문서에 적힌 대로 이 함수는 서버나 독립 실행에서만 불립니다. 그래서 빙의 직후에 클라이언트 화면에서 해야 할 준비를 PossessedBy에만 두면, 네트워크 게임의 클라이언트에서는 그 코드가 실행되지 않습니다.


실제 게임에서 나눠 보기

FPS 게임의 플레이어라면, 플레이어가 직접 조종하는 캐릭터의 모델과 움직임은 ACharacter가 맡고, 마우스와 키보드 입력을 받아 그 캐릭터를 움직이고 총을 쏘게 하며 HUD를 보여 주는 일은 APlayerController가 맡습니다. NPC 적이라면 적의 모델과 움직임은 ACharacter, 플레이어를 쫓거나 공격하는 AI 로직과 이동, 공격 명령은 AAIController가 맡습니다. 차량 시뮬레이션이라면 차량의 물리 모델과 메시는 APawn, 키보드나 게임패드 입력으로 차량을 조작하는 일은 APlayerController가 맡습니다.

이렇게 나눠 보면 기준이 드러납니다. 몸체에 사람형 보행과 점프, 네트워크 이동 예측이 필요하면 ACharacter를 고르고, 다른 이동 방식을 직접 조립해야 한다면 APawn과 알맞은 이동 컴포넌트를 검토합니다. 누가 조종하느냐는 몸체와 따로 정하므로, 같은 캐릭터 클래스를 플레이어와 AI가 모두 조종할 수도 있습니다.


정리

  • APawn은 컨트롤러가 빙의해 조종할 수 있는 액터이며, 메시와 이동 로직은 컴포넌트로 더합니다. 사람형이 아닌 조종 대상에 알맞습니다.
  • ACharacter는 캡슐 충돌, 스켈레탈 메시, UCharacterMovementComponent를 갖춘 폰으로, 사람형 이동과 네트워크 이동 동기화를 제공합니다.
  • APlayerController는 플레이어의 입력과 UI, 플레이어별 관리를 맡고, 서버와 그 플레이어의 클라이언트에 존재합니다. AAIController는 행동 트리, 지각, 내비게이션으로 AI를 조종합니다.
  • Possess와 UnPossess는 조종 연결만 바꾸며, 객체를 만들거나 파괴하거나 상태를 복사하지 않습니다. 게임 중에 스폰한 폰은 자동으로 빙의되지 않습니다.
  • 연결은 GetPawn()과 GetController()로 확인하고, 다른 클라이언트가 알아야 할 플레이어 상태는 PlayerState 같은 곳에 둡니다.

연습 문제

1. UnPossess만 호출하면

앞의 예에서 C가 B를 조종하고 있을 때 UnPossess만 호출했습니다. 다른 조종자, 생성, 파괴, 상태 복사 처리는 없고 두 객체는 유효하게 남아 있습니다. C의 GetPawn()과 B의 GetController()는 무엇을 가리킬까요? B에 독립적으로 동작하는 물리나 이동 로직이 있다면, UnPossess만으로 모든 움직임이 멈춘다고 판단해도 될까요?

해설 보기

서로를 가리키던 조종 참조가 해제되므로 두 조회 모두 더 이상 상대를 가리키지 않고, 이 조건에서는 null이 나오는지 확인합니다. 두 객체는 그대로 남아 있습니다.

빙의 해제는 독립된 물리나 이동 로직을 끄는 명령이 아니므로, B의 움직임이 멈춘다고 판단할 수 없습니다. 멈춰야 한다면 이동 정지, 입력 해제, 상태 정리를 따로 처리해야 합니다.

2. Pawn과 Character 고르기

탱크처럼 바퀴로 움직이며 포탑을 돌리는 조종 대상과, 걷고 점프하는 사람형 NPC를 만들려고 합니다. 각각 APawn과 ACharacter 가운데 무엇을 부모로 고르는 것이 알맞을까요? 두 대상을 모두 플레이어가 조종할 수도 있다면 컨트롤러는 어떻게 될까요?

해설 보기

탱크는 사람형 보행과 다른 이동 방식이 필요하므로 APawn을 부모로 하고, 필요한 이동 컴포넌트를 직접 조립합니다. 사람형 NPC는 걷기와 점프, 이동 동기화가 이미 구현된 ACharacter를 부모로 고르는 편이 알맞습니다.

몸체와 조종자는 따로 정하므로, 두 대상 모두 플레이어의 APlayerController가 빙의해 조종할 수도 있고 AAIController가 조종할 수도 있습니다. 부모 클래스를 고르는 일과 누가 조종할지를 정하는 일은 별개입니다.

Possess가 권한 쪽에서만 실행된다는 조건은 Epic의 AController::Possess API 문서에서, 폰의 기본 조종 관계와 게임 중에 스폰한 폰이 자동으로 빙의되지 않는다는 점은 Pawn 문서에서 확인할 수 있습니다.

다음 글 입력 처리(Input Mapping)에서는 향상된 입력(Enhanced Input)으로 입력 액션과 매핑 컨텍스트를 만들고, 컨트롤러와 캐릭터에서 입력을 처리하는 방법을 살펴봅니다.