Possess를 하지 않았을 때, Character의 PlayerState 처리

sangmiha·2024년 9월 10일

Unreal

목록 보기
2/4

발단

레벨간에 'Character'를 꼭 Possess를 하지는 않고 관찰하는 형식만 필요한 경우가 있다.
이럴 때 보통 Possess를 하지 않고 'spectator mode'로 컨트롤러를 사용하게 된다.

하지만 캐릭터 별로 구분하여 데이터가 필요한 경우가 있을 수 있다. 내 경우에는 컨트롤러가 굳이 필요하지 않지만 PlayerState로 캐릭터를 구분하여 내부 객체를 탐색해야할 필요가 있었다.

내부 에러가 이상하게 처리되어서 좀 헤멘 부분이 있었는데 이를 포함해서 포스팅에서 아래와 같은 내용을 다루려 한다.

  1. Possess를 하지 않을 경우, Character가 PlayerState를 가지지 않는 이유를 언리얼 내부 코드를 보면서 밝혀낸다.
  2. 1번에서 살펴본 내용을 토대로 Possess를 하지 않고 Controller와 특정 Character가 같은 PlayerState를 공유하고자 한다면 어떻게 하는지 알아본다.
  3. 내가 겪은 에러 상황을 살펴본다.

에러 부분은 중요하게 다루진 않을 거지만 에러가 이상한 부분에서 터지는 것이 이상하여 기록한다.

'Possess'의 내부 구현

Possess의 구현을 따라가서 PlayerState를 세팅하는 부분의 주요 코드를 보면 다음과 같다.

if (Controller->PlayerState != nullptr)
{
	SetPlayerState(Controller->PlayerState);
}

직관적으로 Controller 내부에 PlayerState가 있다면 캐릭터 객체 내부에서 SetPlayerState를 사용하여 Controller의 PlayerState를 그대로 Character에 설정한다.

'Possess'없이 PlayerState를 캐릭터에 부여

if (PC->PlayerState)
{
	DPC->SetPlayerState(PC->PlayerState);
}

1번을 통해서 알 수 있는 내용이다. 내부 구현과 똑같이 'PC'내부에 'PlayerState'가 있는지 확인하고 캐릭터 객체의 SetPlayerState로 'PC'의 'PlayerState'를 설정한다.

이렇게 하면 언리얼의 Possess과정 없이 PlayerState만 공유하도록 설정할 수 있다.

의아한 에러 공유

Possess를 하지 않고 실수로 'Character' 내부에서 GetPlayerState를 호출했는데 해당 부분에서 Error가 발생하는게 아니라 실질적으로 사용하는 부분에서 문제가 발생했다.

int32 PlayerId = GetPlayerState()->GetPlayerId(); // 예상되는 에러 지점
				
FNetLogger::EditerLog(FColor::Green, TEXT("Local PlayerControlled"));

if (TTM)
{
	TTM->SendLargeDataInChunks(
	DynamicTextureComponent->CompressTextureDataToEXR(),
	PS->GetPlayerId()); // 실제로 에러가 생긴 지점
}

위의 문제 때문에 엉뚱한 부분에서 에러가 생긴다고 착각했고 필요이상으로 시간이 걸렸다.

언리얼 내부적으로 최적화가 이루어진다고 생각된다.

0개의 댓글