Player Controller

 

작성 기준 버전 :: 4.21.1

 

언리얼 엔진에서 Player Controller는 Pawn과 그것을 제어하려는 사람 사이의 인터페이스로서, 플레이어의 의지를 대변하는 클래스이다. Player Controller는 Controller 클래스를 상속받는데, Possess() 함수로 Pawn의 제어권을 획득하고, UnPossess() 함수로 제어권을 포기한다.

 

컨트롤러에 대한 언리얼 문서

 

플레이어 컨트롤러에 대한 언리얼 문서

 

이러한 설명이 언리얼 문서 상에서의 Player Controller에 대한 내용의 대부분이고, 실제적인 C++ 코드에서의 사용법은 레퍼런스에서 찾아서 멤버 변수와 함수 등을 직접 찾아서 읽어야 하는 불편함이 있기 때문에 입문자는 Player Controller의 사용법을 제대로 익히기가 쉽지 않다.

 

그럼 이제부터 Player Controller의 기본적인 기능과 사용법에 대해서 알아보도록 하자.

 

 

마우스 인터페이스

 

플레이어 컨트롤러가 기본적으로 제공하는 기능 중에는 마우스 인터페이스에 관련된 기능이 있다.

 

플레이어 컨트롤러를 상속받는 블루프린트 클래스를 만들고 에디터를 열어보면 디테일 패널의 Mouse Interface 카테고리에서 플레이어 컨트롤러가 기본적으로 제공하는 마우스 인터페이스와 관련된 기능들을 한눈에 볼 수 있다. 디테일 패널에서 보이는 것들은 아주 기본적인 내용으로 이보다 심도깊은 기능에 대해서 배우고자 한다면 APlayerController 클래스의 언리얼 레퍼런스를 확인하는게 좋다.

 

 

bEnableClickEvents = true;
bEnableTouchEvents = true;
bEnableMouseOverEvents = true;
bEnableTouchOverEvents = true;

 

C++ 코드 상에서는 UPlayerController 클래스의 위와 같은 프로퍼티들을 통해서 옵션을 바꿀 수 있다.

 

Show Mouse Cursor

 

Show Mouse Cursor 옵션은 말 그대로 게임 도중에 마우스 커서를 보이게 할 것인가에 대한 옵션이다. 예를 들어보자면, 전통적인 PC 플랫폼에서의 탑다운뷰 RPG 게임은 캐릭터를 이동시킬 때 주로 마우스를 이용한다. 때문에 커서가 항상 보이도록 이 옵션을 true로 해줘야 한다. 하지만 FPS 게임은 화면 중앙의 크로스헤어에 적을 일치시키고 공격하는 방식이기 때문에 커서가 보일 필요가 없다. 혹은 위 두 가지 사례가 융합된 장르들은 전투나 이동 같은 플레이 중일 때는 커서를 비활성화시킨 상태로 크로스헤어를 사용하고, 인벤토리나 지도를 열면 커서를 활성화시키는 방식으로 사용하기도 한다.

 

bShowMouseCursor = true;

bShowMouseCursor = false;

 

C++ 코드 상에서는 UPlayerController 클래스의 bShowMouseCursor 프로퍼티를 통해서 옵션을 바꿀 수 있다.

 

Event

 

그 다음 네 가지 옵션은 월드에 배치된 액터/컴포넌트가 마우스나 터치에 대해서 이벤트를 발생시킬지에 대한 프로퍼티이다.

 

Click Event / Touch Event는 액터/컴포넌트에 대한 클릭/터치 이벤트이고, Mouse Over Event / Touch Over Event는 액터/컴포넌트에 커서나 터치가 올라가 있는 상태에 대한 이벤트이다.

 

간단하게 예시를 보자면 언리얼 프로젝트에 테스트용 C++ 클래스를 하나 만들고 NotifyActorOnClicked() 함수를 덮어씌워서 다음과 같이 구현하고 프로젝트를 다시 빌드한다.

 

virtual void NotifyActorOnClicked(FKey PressedButton = EKeys::LeftMouseButton) override;

 

void AClickEventTestActor::NotifyActorOnClicked(FKey PressedButton)
{
    UE_LOG(LogTemp, Log, TEXT("NotifyActorOnClicked"));
}

 

그리고 새 Player Controller를 하나 만들어서 Show Mouse Cursor와 Enable Click Event를 true로 설정한 뒤, 프로젝트 설정의 맵 & 모드에서 기본 플레이어 컨트롤러로 설정한다.

 

그 다음 아까 만든 액터를 레벨에 배치하고 클릭할 수 있게 스태틱 메시 컴포넌트를 추가해주자.

 

레벨 에디터에서 플레이 버튼을 누르고 추가한 액터를 클릭해보면 출력 로그 패널에서 "NotifyActorOnClicked"라고 출력되는 것을 확인할 수 있다.

 

 

액터나 컴포넌트에 Click Event를 추가했더라도 Player Controller에서 Enable Click Event를 false로 설정했다면, NotifyActorOnClicked() 이벤트는 호출되지 않는다.

 

Default Mouse Cursor

 

Default Mouse Cursor 프로퍼티는 기본적인 마우스 커서 모양을 정하는 프로퍼티이다. 커서 모양의 종류는 언리얼 문서에서 확인할 수 있다.

 

DefaultMouseCursor = EMouseCursor::Default;

 

C++ 코드 상에서는 UPlayerController 클래스의 DefaultMouseCursor 프로퍼티를 통해서 옵션을 바꿀 수 있다.

 

Default Click Trace Channel

 

Default Click Trace Channel은 클릭 이벤트가 발생했을 때, 플레이어가 클릭한 대상을 3D 공간에서 찾기 위해서 트레이스를 통해 광선 같은 개념의 선을 쏘는데 어떤 채널에 속하는 객체가 맞았을 때 찾았다고 판정할 지를 정하는 프로퍼티이다. "Visibility"가 기본값으로 되어 있는데, 이는 화면에 보이는 객체가 맞으면 무조건 맞았다고 판정한다는 의미이다.

 

이 값의 종류에는 Visibility 이 외에도, Pawn만 찾아내는 Pawn, 월드에 스태틱으로 배치된 액터만 찾아내는 WorldStatic 등이 있다.

 

DefaultClickTraceChannel = ECollisionChannel::ECC_Visibility;

 

C++ 코드 상에서는 UPlayerController 클래스의 DefaultClickTraceChannel 프로퍼티를 통해서 옵션을 바꿀 수 있다.

 

Trace Distance

 

Trace Distance 프로퍼티는 클릭 이벤트 등이 발생했을 때, 화면으로부터 얼마나 멀리 떨어진 지점까지 대상을 탐색할 것인가에 대한 것이다.

 

HitResultTraceDistance = 10000.0f;

 

그 외의 유용한 마우스 관련 함수

 

1. GetHitResultUnderCursor()

 

GetHitResultUnderCursor() 함수는 함수 이름 그대로 화면에서 마우스 커서 위치에 트레이스를 쏴서 그 결과를 가져오는 함수이다. 일반적인 함수의 사용법은 아래와 같으며, 이 함수는 레벨에 배치된 오브젝트를 선택하거나, RPG 식으로 클릭한 위치로 캐릭터를 이동시킬 때, 유용하게 사용할 수 있다.

 

FHitResult Hit;
GetHitResultUnderCursor(ECC_Visibility, false, Hit);

if (Hit.bBlockingHit)
{
    // 충돌 결과가 있을 때의 처리
}

 

 

플레이어 틱(Player Tick)

 

플레이어 컨트롤러는 액터 클래스에서 상속받는 Tick() 함수 외에 PlayerTick() 이라는 별도의 틱 함수를 하나 더 가진다. 일반 Tick() 함수는 어디서나 작동하는 반면에, PlayerTick() 함수는 Player Controller에 PlayerInput 객체가 있는 경우에만 호출된다. 따라서 로컬로 제어되는 Player Controller에서만 플레이어 틱이 호출된다. 이 말인 즉슨, 만약 멀티플레이 게임이라면 자기 자신의 플레이어 컨트롤러에서만 플레이어 틱이 호출된다는 것이다.

 

virtual void PlayerTick(float DeltaTime) override;

 

void ATestPlayerController::PlayerTick(float DeltaTime)
{
    Super::PlayerTick(DeltaTime);

}

 

플레이어 틱 함수를 덮어쓰기 위해서는 위와 같이 코드를 작성하면 된다.

 

 

폰(Pawn)

 

플레이어 컨트롤러는 기본적으로 자신이 빙의(Possess)하여 컨트롤하는 폰을 레퍼런스로 가지고 있게 된다. 일반적으로 프로젝트 세팅의 맵 & 모드나 월드 세팅에서 디폴트 폰을 None이 아닌 특정 폰으로 설정해둔 상태라면, 게임이 시작되면 폰이 생성되고 플레이어 컨트롤러는 생성된 폰에 자동으로 빙의된다.

 

디폴트 폰이 None이어서 자동으로 빙의되는 상황이 아니라면, Possess() 함수를 이용하여 빙의하고자 하는 폰에 컨트롤러를 빙의시키면된다.

 

Possess(TargetPawn);

 

이 반대의 경우로 현재 빙의하고 있는 폰에서 제어권을 포기하고 탈출하려고 한다면 UnPossess() 함수를 사용하면 된다.

 

UnPossess();

 

컨트롤러가 빙의 중인 폰을 가져와서 사용하기 위해서는 다음과 같이 GetPawn() 함수를 사용하면 된다.

 

APawn* MyPawn = GetPawn();

 

만약에 컨트롤러가 현재 컨트롤 중인 폰이 없는 상태라면 GetPawn() 함수는 nullptr를 반환한다.

 


 

[투네이션]

 

-

 

toon.at

[Patreon]

 

WER's GAME DEVELOP CHANNEL님이 Game making class videos 창작 중 | Patreon

WER's GAME DEVELOP CHANNEL의 후원자가 되어보세요. 아티스트와 크리에이터를 위한 세계 최대의 멤버십 플랫폼에서 멤버십 전용 콘텐츠와 체험을 즐길 수 있습니다.

www.patreon.com

[디스코드 채널]

 

Join the 베르의 게임 개발 채널 Discord Server!

Check out the 베르의 게임 개발 채널 community on Discord - hang out with 399 other members and enjoy free voice and text chat.

discord.com

 

반응형

+ Recent posts