플레이어의 데이터를 저장 하고 불러오는 기능 구현 방식
언리얼 오브젝트를 상속 받은 SaveGame 클래스 설계
세이브 시스템에 SaveGame 데이터를 넘겨주면 저장 과 로딩을 쉽게 구현
에디터에서 저장 할 경우 Save 폴더에 있는 SaveGames 폴더에 게임 데이터가 저장
SaveGame 상속 받은 ABSaveGame 클래스 생성
각 저장 파일에 접근 할려면 고유 이름은 슬롯 이름 필요
기본 세이브 데이터를 생성 하는 로직으로 플레이어 스테이트 구현
UCLASS()
class ARENABATTLE_API UABSaveGame : public USaveGame
{
GENERATED_BODY()
public:
UABSaveGame();
//레벨 저장 변수
UPROPERTY()
int32 Level;
//경험치 저장 변수
UPROPERTY()
int32 Exp;
//플레이어 이름 저장 변수
UPROPERTY()
FString PlayerName;
//스코어 저장 변수
UPROPERTY()
int32 HighScore;
};
#include "ABSaveGame.h"
UABSaveGame::UABSaveGame()
{
//각 변수 데이터 초기화
Level = 1;
Exp = 0;
PlayerName = TEXT("Guest");
HighScore = 0;
}
ABPlayState
ABSaveGame 사용 할 수 있게 slot name 지정
Slotname 으로 데이터 로드 후 저장된 값이 없다면 기본 데이터로 슬롯 초기화
UCLASS()
class ARENABATTLE_API AABPlayerState : public APlayerState
{
GENERATED_BODY()
public:
//가장 높은 점수 리턴
int32 GetGameHighScore() const;
//저장할 슬롯 네임
FString SaveSlotName;
protected:
//가장 높은 스코어
UPROPERTY(Transient)
int32 GameHighScore;
}
#include "ABSaveGame.h"
AABPlayerState::AABPlayerState()
{
CharacterLevel = 1;
GameScore = 0;
Exp = 0;
GameHighScore = 0;
SaveSlotName = TEXT("Player1");
}
int32 AABPlayerState::GetGameHighScore() const
{
return GameHighScore;
}
void AABPlayerState::InitPlayerData()
{
//세이브 슬롯 네임에 해당하는 SaveGame 데이터 로드
auto ABSaveGame = Cast<UABSaveGame>(UGameplayStatics::LoadGameFromSlot(SaveSlotName, 0));
if (nullptr == ABSaveGame)
{
//만약 해당 슬롯이 없다면 기본 데이터로 초기화
ABSaveGame = GetMutableDefault<UABSaveGame>();
}
SetPlayerName(ABSaveGame->PlayerName);
SetCharacterLevel(ABSaveGame->Level);
GameScore = 0;
GameHighScore = ABSaveGame->HighScore;
Exp = ABSaveGame->Exp;
}
void AABPlayerState::AddGameScore()
{
//스코어 증가
GameScore++;
//최대 스코어 판단 후 갱신
if (GameScore >= GameHighScore)
{
GameHighScore = GameScore;
}
//Playstate 업데이트
OnPlayerStateChanged.Broadcast();
}
플레이어 데이터 변경 시 자동 저장 기능 구현
PlayerState
경험치 변동 시 데이터 저장 하는 로직
최초에 플레이어 데이터 로드 후 바로 저장
UCLASS()
class ARENABATTLE_API AABPlayerState : public APlayerState
{
GENERATED_BODY()
public:
//player state 저장
void SavePlayerData();
}
void AABPlayerState::InitPlayerData()
{
//세이브 슬롯 네임에 해당하는 SaveGame 데이터 로드
auto ABSaveGame = Cast<UABSaveGame>(UGameplayStatics::LoadGameFromSlot(SaveSlotName, 0));
if (nullptr == ABSaveGame)
{
//만약 해당 슬롯이 없다면 기본 데이터로 초기화
ABSaveGame = GetMutableDefault<UABSaveGame>();
}
SetPlayerName(ABSaveGame->PlayerName);
SetCharacterLevel(ABSaveGame->Level);
GameScore = 0;
GameHighScore = ABSaveGame->HighScore;
Exp = ABSaveGame->Exp;
//데이터 로드 후 저장
SavePlayerData();
}
bool AABPlayerState::AddExp(int32 IncomeExp)
{
if (CurrentStatData->NextExp == -1)
return false;
//레벨업 판단
bool DidLevelUp = false;
//현재 경험치에 변수 값을 더하고
Exp = Exp + IncomeExp;
if (Exp >= CurrentStatData->NextExp)
{
//레벨 업 경험치를 넘어갈 경우 레벨 업 동작
Exp -= CurrentStatData->NextExp;
SetCharacterLevel(CharacterLevel + 1);
DidLevelUp = true;
}
//플레이어 스테이트 변경 델리게이트 실행
OnPlayerStateChanged.Broadcast();
//경험치 변경으로 데이터 저장
SavePlayerData();
return DidLevelUp;
}
void AABPlayerState::AddGameScore()
{
//스코어 증가
GameScore++;
//최대 스코어 판단 후 갱신
if (GameScore >= GameHighScore)
{
GameHighScore = GameScore;
}
//Playstate 업데이트
OnPlayerStateChanged.Broadcast();
//스코어 변경으로 데이터 저장
SavePlayerData();
}
void AABPlayerState::SavePlayerData()
{
//게임 세이브 클래스 생성
UABSaveGame* NewPlayerData = NewObject<UABSaveGame>();
NewPlayerData->PlayerName = GetPlayerName();
NewPlayerData->Level = CharacterLevel;
NewPlayerData->Exp = Exp;
NewPlayerData->HighScore = GameHighScore;
//해당 SaveGame 을 slotname에 저장
if (!UGameplayStatics::SaveGameToSlot(NewPlayerData, SaveSlotName, 0))
{
ABLOG(Error, TEXT("SaveGame Error!"));
}
}
NewObject
언리얼 오브젝트 생성 시 NewObject 명령을 사용 시
언리얼 실행 환경에서 가비지 컬렉션 자동으로 소멸
수동으로 delete 키워드를 사용 하지 않아도 된다
하이 스코어 값을 HUD UI 연동
void UABHUDWidget::UpdatePlayerState()
{
//약 포인트 연결 확인
ABCHECK(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())));
}
저장 데이터 확인
프로젝트의 Saved 폴더 내 SaveGames 폴더 에서 확인
파일명은 슬롯 이름과 동일
'언리얼 C++ 게임 개발의 정석 > 14. 게임의 완성' 카테고리의 다른 글
14.4 게임 중지 와 결과 화면 (0) | 2024.06.02 |
---|---|
14.3 타이틀 화면 제작 (0) | 2024.06.01 |
14.2 전투 시스템 설계 (0) | 2024.05.27 |