1. SaveGame을 상속받은 cpp 클래스를 생성해주고, 저장하고싶은 데이터들을 멤버로 넣어줍니다.
// MySaveGame.h
#pragma once
#include "GameInfo.h"
#include "GameFramework/SaveGame.h"
#include "MySaveGame.generated.h"
UCLASS()
class ESCAPEGAME_API UMySaveGame : public USaveGame
{
GENERATED_BODY()
public:
UMySaveGame();
public:
// 게임 상태
UPROPERTY(VisibleAnywhere, Category = Basic)
FVector SaveLocation;
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 LevelIndex;
UPROPERTY(VisibleAnywhere, Category = Basic)
float PlayTime;
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 DeathCount;
// 인벤토리
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 NoPainPotionCount; // 0
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 InvisibleClockCount; // 1
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 PenetrateStoneCount; // 2
// 슬롯 이름과 인덱스
UPROPERTY(VisibleAnywhere, Category = Basic)
FString SaveSlotName;
UPROPERTY(VisibleAnywhere, Category = Basic)
int32 UserIndex;
};
// MySaveGame.cpp
#include "MySaveGame.h"
UMySaveGame::UMySaveGame()
{
SaveSlotName = TEXT("EscapeGameSaveSlot");
UserIndex = 0;
}
2. 메뉴에서 세이브 버튼을 누르면 플레이어에서 세이브를 해줍니다.
void AMyPlayerCharacter::SaveGameState()
{
UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
UEscapeGameInstance* GameInst = Cast<UEscapeGameInstance>(GetGameInstance());
AMainGameMode* GameMode = Cast<AMainGameMode>(GetWorld()->GetAuthGameMode());
if (IsValid(GameMode))
{
UWidgetMainHUD* MainHUD = GameMode->GetWidgetMainHUD();
if (IsValid(MainHUD))
{
Inventory = MainHUD->GetInventory();
}
}
// List에 아이템 세팅
List = Inventory->GetList();
if (IsValid(SaveGameInstance) && IsValid(GameInst))
{
// 플레이어 상태 저장
SaveGameInstance->PlayTime = GameInst->fPlayTime;
SaveGameInstance->DeathCount = GameInst->iDeathCount;
SaveGameInstance->LevelIndex = GameInst->GetLevelIndex();
SaveGameInstance->SaveLocation = GetActorLocation();
// 인벤토리 저장
SaveGameInstance->NoPainPotionCount = Cast<UInventoryItemData>(List->GetItemAt(0))->GetItemCount();
SaveGameInstance->InvisibleClockCount = Cast<UInventoryItemData>(List->GetItemAt(1))->GetItemCount();
SaveGameInstance->PenetrateStoneCount = Cast<UInventoryItemData>(List->GetItemAt(2))->GetItemCount();
UGameplayStatics::SaveGameToSlot(SaveGameInstance, SaveGameInstance->SaveSlotName, SaveGameInstance->UserIndex);
}
}
세이브 버튼을 누르면 프로젝트의 Saved 폴더에 .sav 파일이 생성됩니다.
3. 플레이어의 비긴플레이쪽에서 세이브 데이터들을 로드해줍니다.
void AMyPlayerCharacter::BeginPlay()
{
Super::BeginPlay();
PlayerAnim = Cast<UMyPlayerAnim>(GetMesh()->GetAnimInstance());
AMainGameMode* GameMode = Cast<AMainGameMode>(GetWorld()->GetAuthGameMode());
if (IsValid(GameMode))
{
UWidgetMainHUD* MainHUD = Cast<UWidgetMainHUD>(GameMode->GetWidgetMainHUD());
if (IsValid(MainHUD))
{
Inventory = MainHUD->GetInventory();
List = Inventory->GetList();
}
}
UEscapeGameInstance* GameInst = Cast<UEscapeGameInstance>(GetGameInstance());
if (IsValid(GameInst))
{
if (GameInst->GetIsNewGame())
{
//GameInst->ResetGameInstance();
}
// New Game이 아니라면
else
{
// 저장된 정보들을 불러온다
if (GameInst->bLoadEnable)
{
UMySaveGame* LoadInst = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
LoadInst = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(LoadInst->SaveSlotName, LoadInst->UserIndex));
SetActorLocation(LoadInst->SaveLocation);
GameInst->SetLevelIndex(LoadInst->LevelIndex);
GameInst->LoadPlayTime(LoadInst->PlayTime);
GameInst->SetDeathCount(LoadInst->DeathCount);
Cast<UInventoryItemData>(List->GetItemAt(0))->SetItemCount(LoadInst->NoPainPotionCount);
Cast<UInventoryItemData>(List->GetItemAt(1))->SetItemCount(LoadInst->InvisibleClockCount);
Cast<UInventoryItemData>(List->GetItemAt(2))->SetItemCount(LoadInst->PenetrateStoneCount);
GameInst->bLoadEnable = false;
}
}
}
}
4. 세이브 데이터가 있는지에 따라 스타트레벨에서도 조건 변화를 줍니다.
void UWidgetStartLevel::ButtonNewGameCallback()
{
UMySaveGame* LoadInst = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
LoadInst = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(LoadInst->SaveSlotName, LoadInst->UserIndex));
// 세이브한 데이터가 있다면
if (IsValid(LoadInst))
{
// 세이브 파일 있다고 메세지 출력
CheckNewGame->VisibleCheck(ESlateVisibility::Visible);
}
// 그렇지 않다면 정상적으로 실행
else
{
UEscapeGameInstance* GameInst = Cast<UEscapeGameInstance>(GetGameInstance());
if (IsValid(GameInst))
{
GameInst->bLoadEnable = false;
GameInst->SetLevelIndex();
uint8 LevelIndex = GameInst->GetLevelIndex();
UGameplayStatics::OpenLevel(GetWorld(), GameInst->LevelArray[LevelIndex]);
}
}
}
void UWidgetStartLevel::ButtonContinuePlayCallback()
{
UMySaveGame* LoadInst = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
LoadInst = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(LoadInst->SaveSlotName, LoadInst->UserIndex));
// 세이브한 데이터가 있다면 세이브 지점으로
if (IsValid(LoadInst))
{
UEscapeGameInstance* GameInst = Cast<UEscapeGameInstance>(GetGameInstance());
if (IsValid(GameInst))
{
GameInst->SetIsNewGame(false);
GameInst->bLoadEnable = true;
GameInst->SetLevelIndex(LoadInst->LevelIndex);
uint8 LevelIndex = GameInst->GetLevelIndex();
UGameplayStatics::OpenLevel(GetWorld(), GameInst->LevelArray[LevelIndex]);
}
}
// 그렇지 않다면
else
{
// 저장된 파일 없다고 메세지 출력
CheckContinueGame->VisibleCheck(ESlateVisibility::Visible);
}
}
5. 관련 UI 제작
세이브한 게임이 있는데 뉴게임 버튼을 눌렀을 때, 체크해주는 메세지를 출력합니다.
세이브한 게임이 없는데 컨티뉴게임을 누르면 체크메세지를 출력합니다.
'게임 개발 (언리얼 엔진)' 카테고리의 다른 글
UE4 게임 개발 EscapeGame - 21 : 패키징 (0) | 2020.12.29 |
---|---|
UE4 게임 개발 EscapeGame - 20 : 게임 엔딩 제작 (0) | 2020.12.28 |
UE4 게임 개발 EscapeGame - 18 : 각종 수정 사항 (0) | 2020.12.27 |
UE4 게임 개발 EscapeGame - 17 : 인벤토리 (0) | 2020.12.27 |
UE4 게임 개발 EscapeGame - 16 : 게임다워지는 과정 (0) | 2020.12.25 |