본문 바로가기
언리얼 C++ 게임 개발의 정석/13. 게임 플레이 제작

13.3 게임 데이터의 관리

by ftftgop3 2024. 5. 23.

새로운 레벨 추가

Gameplay 새로운 레벨 제작 후 네비게이션 크기를 x :100000, y : 100000 확장

게임 스코어

처음에 0으로 시작 NPC를 죽이면 1 상승

현재 프로젝트는 싱글 플레이 게임으로 플레이어 스테이트에 추가 하면 되지만

멀티 플레이를 고려해 게임 스테이트를 이용

 

ABGameState 생성

스코어 점수 변수 추가 후 데이터 관리 

UCLASS()
class ARENABATTLE_API AABGameState : public AGameStateBase
{
	GENERATED_BODY()

public:
	AABGameState();

public:
	//도탈 점수 리턴
	int32 GetTotalGameScore() const;
	//점수 추가
	void AddGameScore();

private:
	//점수 
	UPROPERTY(Transient)
		int32 TotalGameScore;
};
#include "ABGameState.h"

AABGameState::AABGameState()
{
	TotalGameScore = 0;
}

int32 AABGameState::GetTotalGameScore() const
{
	return TotalGameScore;
}

void AABGameState::AddGameScore()
{
	TotalGameScore++;
}

Gamemode에 현재 게임 상태로 지정 

#include "ABGameState.h"

AABGameMode::AABGameMode()
{
	DefaultPawnClass = AABCharacter::StaticClass();
	PlayerControllerClass = AABPlayerController::StaticClass();
	//플레이어 스테이트 지정
	PlayerStateClass = AABPlayerState::StaticClass();
	GameStateClass = AABGameState::StaticClass();
}

 

Section

NPC 사망 시 Secion의 상태를 Complete 변경

NPC 제거 시 마지막에 대미지를 입힌 컨트롤러의 기록은 LastHitBy 속성에 저장

UCLASS()
class ARENABATTLE_API AABSection : public AActor
{
	GENERATED_BODY()
    private:
    //NCP 사망 시 실행 하는 델리게이트 함수에 등록
    UFUNCTION()
		void OnKeyNPCDestroyed(AActor* DestroyedActor);
}
void AABSection::OnNPCSpawn()
{
	//생성 핸들러 초기화
	GetWorld()->GetTimerManager().ClearTimer(SpawnNPCTimerHandle);
	//현재 섹션의 중앙의 Y 값 88 위치에서 생성
	auto KeyNPC = GetWorld()->SpawnActor<AABCharacter>(GetActorLocation() + FVector::UpVector * 88.0f, FRotator::ZeroRotator);
	if (nullptr != KeyNPC)
	{
		//npc 객체 파괴 시 실행하는 델리게이트에 함수 등록
		KeyNPC->OnDestroyed.AddDynamic(this, &AABSection::OnKeyNPCDestroyed);
	}
	
}

void AABSection::OnKeyNPCDestroyed(AActor * DestroyedActor)
{
	//파괴된 엑터가 캐릭터 객체이면 LastHitBy 플레이어일 경우 COMPLETE 변경
	auto ABCharacter = Cast<AABCharacter>(DestroyedActor);
	ABCHECK(nullptr != ABCharacter);
	
	auto ABPlayerController = Cast<AABPlayerController>(ABCharacter->LastHitBy);
	ABCHECK(nullptr != ABPlayerController);

	SetState(ESectionState::COMPLETE);
}

 

ABPlayState

플레이어의 점수 증가 기능 구현

UCLASS()
class ARENABATTLE_API AABPlayerState : public APlayerState
{
	GENERATED_BODY()
	
	public:
	//게임 스코어 값 증가
	void AddGameScore();
}
void AABPlayerState::AddGameScore()
{
	//스코어 증가
	GameScore++;
	//Playstate 업데이트
	OnPlayerStateChanged.Broadcast();
}

ABPlayerController

컨트롤러에서 ABPlayState 접근해 AddGameScore 함수 호출 

UCLASS()
class ARENABATTLE_API AABPlayerController : public APlayerController
{
	GENERATED_BODY()
    public:
    	//스코어 점수 증가
	void AddGameScore() const;
}
//현재 스테이트에서 점수 증가
void AABPlayerController::AddGameScore() const
{
	ABPlayerState->AddGameScore();
}

 

 

GameMode 전체 스코어 점수 기능 추가

마지막 피격을 가한 플레이어 컨트롤러 정보를 가지고 

NPC를 죽인 컨트롤러와 동일한 컨트롤러 검색 해 스코어 증가 

전체 스코어 증가 기능 추가

UCLASS()
class ARENABATTLE_API AABGameMode : public AGameModeBase
{
	GENERATED_BODY()

public:
	AABGameMode();
	
	virtual void PostLogin(APlayerController* NewPlayer) override;
	//게임 스테이트 변수에 지정
	virtual void PostInitializeComponents() override;
	//게임 전체 스코어 증가
	void AddScore(class AABPlayerController *ScoredPlayer);

private:
	UPROPERTY()
		class AABGameState* ABGameState;
};

//ABGameState 변수에 지정
void AABGameMode::PostInitializeComponents()
{
	Super::PostInitializeComponents();
	ABGameState = Cast<AABGameState>(GameState);
}

//NPC를 죽인 컨트롤러를 매개변수로 검색 해 해당 컨트롤러의 플레이어 스코어 증가
void AABGameMode::AddScore(AABPlayerController* ScoredPlayer)
{
	//현재 월드에 있는 모든 플레이어 컨트롤러에 동작
	for (FConstPlayerControllerIterator It = GetWorld()->GetPlayerControllerIterator(); It; ++It)
	{
		const auto ABPlayerController = Cast<AABPlayerController>(It->Get());
		if ((nullptr != ABPlayerController) && (ScoredPlayer == ABPlayerController))
		{
			//현재 매개변수로 받은 컨트롤러를 찾은 후 점수 증가
			ABPlayerController->AddGameScore();
			break;
		}
	}
	//전체 점수 증가
	ABGameState->AddGameScore();
}

 

Section 

Complete 상태이면 스코어 증가 호출

#include "ABGameMode.h"

void AABSection::OnKeyNPCDestroyed(AActor * DestroyedActor)
{
	//파괴된 엑터가 캐릭터 객체이면 LastHitBy 플레이어일 경우 COMPLETE 변경
	auto ABCharacter = Cast<AABCharacter>(DestroyedActor);
	ABCHECK(nullptr != ABCharacter);
	
	auto ABPlayerController = Cast<AABPlayerController>(ABCharacter->LastHitBy);
	ABCHECK(nullptr != ABPlayerController);
	//게임 모드 호출해 스코어 증가
	auto ABGameMode = Cast<AABGameMode>(GetWorld()->GetAuthGameMode());
	ABCHECK(nullptr != ABGameMode);
	ABGameMode->AddScore(ABPlayerController);
	
	SetState(ESectionState::COMPLETE);
}