[Unreal] Spectator 에서 스팀 이름 가져오기
개요
일단 이걸 하기 전 Online Subsystem Steam 플러그인을 활용하고 이를 통해 세션을 제작해야 합니다. 이 과정을 거치면 PlayerState에서 PlayerName이 스팀의 닉네임으로 설정됩니다. 그리고 이번 글에서 알려드릴 건 이 스팀 닉네임을 Spectator에서 가져오는 것입니다.
Spectator Pawn 에서 관전자를 변경하는 방법
일단 다른 게임에서 보이듯 죽고 나서 관전할 플레이어를 변경할 수 있는 기능을 구현했습니다. 이는 GameMode에서 Spectator Pawn으로 할당하는 Pawn 클래스에서 관리를 하는데 아래 코드와 같은 모습입니다.
void AFASpectatorPawn::SpectateNextPlayer()
{
if (APlayerController* PlayerController = GetController<APlayerController>())
{
PlayerController->ServerViewNextPlayer();
}
}
void AFASpectatorPawn::SpectatePrevPlayer()
{
if (APlayerController* PlayerController = GetController<APlayerController>())
{
PlayerController->ServerViewPrevPlayer();
}
}
여기서 플레이어 컨트롤러의 ServerView~~Player를 사용했습니다. 이 함수는 언리얼에서 제공하는 함수로 다음이나 이전 플레이어를 관전하게 도와주는 함수입니다. 이 함수를 호출하면 카메라 시점이 그 플레이어로 넘어가게 되는 것이죠.
void APlayerController::ServerViewNextPlayer_Implementation()
{
if (IsInState(NAME_Spectating))
{
ViewAPlayer(+1);
}
}
void APlayerController::ServerViewPrevPlayer_Implementation()
{
if (IsInState(NAME_Spectating))
{
ViewAPlayer(-1);
}
}
그런데 파고보면 이 두 함스는 결국 ViewAPlayer라는 함수를 사용하고 있고
void APlayerController::ViewAPlayer(int32 dir)
{
APlayerState* const NextPlayerState = GetNextViewablePlayer(dir);
if ( NextPlayerState != nullptr )
{
SetViewTarget(NextPlayerState);
}
}
void APlayerController::SetViewTarget(class AActor* NewViewTarget, struct FViewTargetTransitionParams TransitionParams)
{
if (PlayerCameraManager)
{
PlayerCameraManager->SetViewTarget(NewViewTarget, TransitionParams);
}
}
ViewAPlayer는 타고 가면 PlayerCameraManager에서 SetViewTarget을 해주는 것임을 알 수 있습니다. 그렇다면 이렇게 설정된 ViewTarget은 어떻게 가져올 수 있을까요? 바로 플레이어 컨트롤러에서 GetViewTarget을 통해 가져올 수 있습니다.
그러면 죽은 사용자(클라이언트)는 서버에서 ViewAPlayer를 부르면 보고 있는 사용자가 달라질 것이고 카메라는 이제 변경된 ViewTarget을 보게 됩니다.
그러면 스팀 아이디를 불러오기 위해서는 이 ViewTarget에서 PlayerState를 가져오면 되는 것입니다.
void APlayableController::ViewAPlayer(int32 dir)
{
Super::ViewAPlayer(dir);
ClientViewTarget();
}
void APlayableController::ClientViewTarget_Implementation()
{
if(GetViewTarget())
{
OnSpectatorViewTargetChanged.Broadcast(GetViewTarget());
}
}
저의 플레이어 컨트롤러에서 ViewAPlayer를 오버라이드 해 줬고 여기서 제가 만든 함수인 ClientViewTarget을 호출해 줬습니다. ViewAPlayer는 서버에서 불리는 함수니 Client RPC로 설정해 줬습니다.
ClientViewTarget은 단순히 델리게이트를 브로드캐스트만 하는데 여기에 GetViewTarget을 넘겨줍니다.
void UDeadWidget::ViewTargetChanged(AActor* ViewTarget)
{
if(SpectatedActorName == nullptr) return;
if(const auto ViewPawn = Cast<APawn>(ViewTarget))
{
if(ViewPawn->GetPlayerState())
{
SpectatedActorName->SetText(FText::FromString(ViewPawn->GetPlayerState()->GetPlayerName()));
}
}
}
그곳에는 이 UI의 함수가 바인딩되어 있는데 여기서 받은 액터를 Pawn으로 변경한 뒤 PlayerState를 가져와야 합니다. Actor에는 그런 게 없으니깐요.
이후 여기서 얻은 PlayerState에서 GetPlayerName을 가져오면 스팀 아이디를 가져올 수 있게 됩니다. 스팀 아이디는 개요에서 말한 대로 Online Subsystem Steam을 활용했다면 PlayerState의 PlayerName에 잘 적용이 되어 있을 겁니다.