[이득우의 언리얼 C++ 게임 개발의 정석] Chapter 14. 게임플레이의 제작

수민·2023년 5월 16일
0
post-thumbnail

이득우의 언리얼 C++ 게임 개발의 정석을 읽고 개인 공부 목적으로 요약 정리한 글입니다!


👀 플레이어 스테이트 (PlayerState)

캐릭터 스테이트 설정

캐릭터를 스테이트 별로 기능을 나눠서 관리하기 위해서 스테이트 머신 모델을 구현하자.

캐릭터 스테이트

  • PREINT : 생성 전 (캐릭터, UI 숨김, 데미지 X)
  • LOADING : 에셋 로딩중, 게임 시작됨 (AI/Player 구분 가능, 조종X, 입력 비활성화)
  • READY : 에셋 로딩 완료 (캐릭터, UI 보여줌, 데미지 O, 조종O, AI Controller O)
  • DEAD : 사망 (UI 숨김, 충돌X, 데미지X, 입력 비활성화, 플레이어-레벨재시작, AI -사라짐)

이 스테이트들은
캐릭터들이 쓸거다
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 초기화 완료


👀 HUD : UI 데이터 연동하기

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();
}

👀 게임 스테이트 (GameState)

게임 스테이트 설정

게임 스테이트는
플레이어들에게 설정된 데이터게임의 데이터를 관리한다.

멀티플레이의 경우,
플레이어1의 점수, 플레이어2의 점수를 모두 관리하고
이 두 가지 정보를 각각의 플레이어에게 리플리케이트해줄 수 있도록 정보를 관리해줄 클래스가 필요하다.ㅇ
이게 바로 게임 스테이트.

데미지 관련 함수

  • 데미지 프레임워크에서 PlayerController의 정보는 Instigator인자로 전달된다.
  • 소멸될 때 마지막으로 데미지를 입힌 Controller의 정보는 LastHitBy 속성에 저장된다.

현재 게임에 참여중인 플레이어 컨트롤러의 목록을 얻는 함수 : GetPlayerControllerIterator

profile
우하하

0개의 댓글