이득우의 언리얼 C++ 게임 개발의 정석을 읽고 개인 공부 목적으로 요약 정리한 글입니다!
캐릭터를 스테이트 별로 기능을 나눠서 관리하기 위해서 스테이트 머신
모델을 구현하자.
캐릭터 스테이트
이 스테이트들은
캐릭터들이 쓸거다
Hunt_Prototype.h
에다가 선언해놓는다.
예제 프로젝트는 싱글플레이이고,
하나의 캐릭터(MyCharacter
)를 플레이어, NPC가 공유해서 쓰고 있음.
캐릭터가 내가 Player인지, NPC인지 알아야 하는데
이걸 알 수 있는 시점이 BeginPlay
그래서 여기서 캐릭터 상태를 초기화한다.
만약 멀티플레이라면,
초기화는BeginPlay
가 아니라OnPossess
에서 해야 한다.
캐릭터의 스탯 정보 (상태)를 관리해줄 PlayerState 를 구현한다.
플레이어 스테이트에는 Level, Exp, Score 등을 넣어 관리해준다.
GameMode의 PlayerStateClass에 만든 PlayerState를 지정해주면
엔진에서 플레이어 컨트롤러가 초기화될 때 이 클래스의 인스턴스를 생성하고,
이 인스턴스의 포인터를 플레이어 컨트롤러의 PlayerState 속성에 저장한다.
-> 플레이어 컨트롤러가 캐릭터에 빙의할 때
캐릭터의 PlayerState 속성에 PlayerState 포인터를 저장하므로
캐릭터에서 해당 PlayerState 정보를 받아올 수 있다.
PlayerController의 구성 완료 시점 == GameMode의 PostLogin
-> 이 때 PlayerState 초기화 완료
UserWidget
을 기본 클래스로 하는 위젯을 만든다.
위젯 인스턴스 생성하는 함수 :
CreateWidget
위젯을 화면에 띄우는 함수 :AddToViewport
HUDWidget = CreateWidget<UMyHUDWidget>(this, HUDWidgetClass); HUNT_CHECK(nullptr != HUDWidget); HUDWidget->AddToViewport(1);
위젯과 PlayerState와 연동해야 하니까
PlayerState에 델리게이트를 정의하고
PlayerState가 변경될 때 위젯을 업데이트하도록 구현한다.
void UMyHUDWidget::BindPlayerState(AMyPlayerState* PlayerState)
{
HUNT_CHECK(nullptr != PlayerState);
CurrentPlayerState = PlayerState;
PlayerState->OnPlayerStateChanged.AddUObject(this, &UMyHUDWidget::UpdatePlayerState);
}
void UMyHUDWidget::NativeConstruct()
{
Super::NativeConstruct();
HPBar = Cast<UProgressBar>(GetWidgetFromName(TEXT("pbHP")));
HUNT_CHECK(nullptr != HPBar);
...
}
void UMyHUDWidget::UpdatePlayerState()
{
HUNT_CHECK(CurrentPlayerState.IsValid());
ExpBar->SetPercent(CurrentPlayerState->GetExpRatio());
PlayerName->SetText(FText::FromString(CurrentPlayerState->GetPlayerName()));
PlayerLevel->SetText(FText::FromString(FString::FromInt(CurrentPlayerState->GetCharacterLevel())));
CurrentScore->SetText(FText::FromString(FString::FromInt(CurrentPlayerState->GetGameScore())));
HighScore->SetText(FText::FromString(FString::FromInt(CurrentPlayerState->GetGameHighScore())));
}
void AMyPlayerController::BeginPlay()
{
Super::BeginPlay();
...
HUDWidget = CreateWidget<UMyHUDWidget>(this, HUDWidgetClass);
HUNT_CHECK(nullptr != HUDWidget);
HUDWidget->AddToViewport(1);
...
HUNT_CHECK(nullptr != MyPlayerState);
HUDWidget->BindPlayerState(MyPlayerState);
MyPlayerState->OnPlayerStateChanged.Broadcast();
}
게임 스테이트는
플레이어들에게 설정된 데이터와 게임의 데이터를 관리한다.
멀티플레이의 경우,
플레이어1의 점수, 플레이어2의 점수를 모두 관리하고
이 두 가지 정보를 각각의 플레이어에게 리플리케이트해줄 수 있도록 정보를 관리해줄 클래스가 필요하다.ㅇ
이게 바로 게임 스테이트.
데미지 관련 함수
- 데미지 프레임워크에서 PlayerController의 정보는 Instigator인자로 전달된다.
- 소멸될 때 마지막으로 데미지를 입힌 Controller의 정보는 LastHitBy 속성에 저장된다.
현재 게임에 참여중인 플레이어 컨트롤러의 목록을 얻는 함수 :
GetPlayerControllerIterator