1. 개요
오늘은 언리얼에서
게임이 재시작 되었을 때 이전에 데이터들을 가져오는
게임 저장 및 로딩에 대해 알아보고자 한다.
2. SaveGame 클래스
게임 데이터를 저장하기 위해서는
2가지를 알아야 한다.
'저장할 데이터'와 '담을 그릇'
게임을 로드하면 캐릭터는 이전에 위치했던 장소에 보여지게 된다.
여기서 저장할 데이터는 "플레이어의 위치"와 "현재 맵"일 것이다.
이 두가지 정보를 알면 특정 맵에 플레이어를 위치시켜줄 수 있다.
다음으로는
언리얼에서 SaveGame 클래스를 제공해준다.

SaveGame 클래스는 저장할 데이터를 담을 그릇이 된다.
그리고 아래와 같이 저장할 데이터들을 변수로 만들어 줄 있다.
#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "MySaveGame.generated.h"
UCLASS()
class TEST002_API UMySaveGame : public USaveGame
{
GENERATED_BODY()
public:
UPROPERTY()
FString Name;
UPROPERTY()
int32 Score = 0;
};

그리고 SaveGame 객체를 생성하면 그릇이 완성된다.
UMySaveGame* saveData =
Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
3. 데이터 저장
그릇을 만든 후에는
저장할 데이터를 담을 수 있게 된다.
if (saveData)
{
saveData->Name = FString("PlayerA");
saveData->Score = 100;
}

그리고 SavGame 객체를
파일로 저장하기 위해 언리얼에서는 동기와 비동기 방식을 지원한다.
데이터 크기가 크다면 디스크에 저장하는 시간이 걸릴 수 있으며
이 경우 비동기 방식으로 저장하는 것이 좋다.
// 비동기 데이터 저장
bool UMyGameInstanceSubsystem::AsyncSave()
{
if (!saveData) return false;
FAsyncSaveGameToSlotDelegate delegate = FAsyncSaveGameToSlotDelegate::CreateUObject(this, &UMyGameInstanceSubsystem::SaveCompleted);
UGameplayStatics::AsyncSaveGameToSlot(saveData, TEXT("Slot01"), 0, delegate);
return true;
}
void UMyGameInstanceSubsystem::SaveCompleted(const FString& SlotName, const int32 UserIndex, bool bSuccess)
{
if (bSuccess)
{
UE_LOG(LogTemp, Log, TEXT("success : AsyncSaveGameToSlot()"));
}
else
{
UE_LOG(LogTemp, Log, TEXT("failed : AsyncSaveGameToSlot()"));
}
}
여기서 핵심은 SaveGame 객체를 비동기적으로 저장하기 위해
UGameplayStatics::AsyncSaveGameToSlot을 사용하였다는 것이다.
그리고 저장에 성공하게 되면
아래에 sav파일이 생성되게 된다.
프로젝트 경로\Saved\SaveGames\Slot01.sav
다음으로 데이터를 동기적으로 저장하고 싶다면
UGameplayStatics::SaveGameToSlot을 사용할 수 있다.
// 동기적 데이터 저장
void UMyGameInstanceSubsystem::Save()
{
if (!saveData) return false;
UGameplayStatics::SaveGameToSlot(saveData, SlotNameGameData, 0);
}
4. 데이터 로드
데이터를 로드는 방법도 동기와 비동기를 지원한다.
저장된 데이터가 많다면 디스크로부터 메모리에 로드하는 시간이 오래 걸리기에
비동기 방식을 선택할 수 있다.
// 비동기 데이터 로딩
bool UMyGameInstanceSubsystem::AsyncLoad()
{
if (!saveData) return false;
// 세이브 파일(Slot01.sav)이 존재하는지 확인한다.
if (!UGameplayStatics::DoesSaveGameExist(TEXT("Slot01"), 0))
{
return false;
}
FAsyncLoadGameFromSlotDelegate delegate = FAsyncLoadGameFromSlotDelegate::CreateUObject(this, &UMyGameInstanceSubsystem::LoadCompleted);
UGameplayStatics::AsyncLoadGameFromSlot(SlotNameGameData, 0, delegate);
return true;
}
void UMyGameInstanceSubsystem::LoadCompleted(const FString& SlotName, const int32 UserIndex, USaveGame* SaveGame)
{
if (SaveGame)
{
UMySaveGame* data = Cast<UMySaveGame>(SaveGame);
saveData->Name = data->Name;
saveData->Score = data->Score;
}
}
비동기 방식으로 데이터를 로드하기 위해
UGameplayStatics::AsyncLoadGameFromSlot를 사용한 것을 확인할 수 있다.
다음으로는 동기 방식으로
데이터를 로드하는 로직이다.
void UMyGameInstanceSubsystem::Load()
{
if (!saveData) return false;
if (!UGameplayStatics::DoesSaveGameExist(SlotNameGameData, 0))
{
return false;
}
UMySaveGame* data = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(SlotNameGameData, 0));
if (!data) return false;
saveData->Name = data->Name;
saveData->Score = data->Score;
}
여기서도 중요한 부분은
UGameplayStatics::LoadGameFromSlot을 사용한다는 것이다.
5. 정리
언리얼에서는 데이터 저장과 로드를 쉽게 구현할 수 있도록
클래스와 API들을 제공해준다.
- SaveGame (그릇)
- UGameplayStatics::AsyncSaveGameToSlot (비동기 저장)
- UGameplayStatics::SaveGameToSlot (동기 저장)
- UGameplayStatics::AsyncLoadGameFromSlot (비동기 로드)
- UGameplayStatics::LoadGameFromSlot (동기 로드)
- 프로젝트 경로\Saved\SaveGames\Slot01.sav (저장 경로)
더 자세한 내용을 참고하고 싶다면
아래 언리얼 공식문서와 블로그를 참고하면 좋을 듯 하다.
게임 저장하기 | 언리얼 엔진 4.27 문서 | Epic Developer Community
【UE5】SaveGameを使ってみよう!(C++編) - main() blog
概要 環境 実装 クラス定義 生成 データをセーブする(非同期) データをロードする(非同期) データをセーブする(同期) データをロードする(同期) 概要 SaveGameは、ゲームの状態を保
www.main-function.com
'Unrael > Basic' 카테고리의 다른 글
| [Gameplay] 애셋 매니저 (AssetManager) (0) | 2025.04.21 |
|---|---|
| [Game] 게임 재미 이론 (0) | 2025.03.21 |
| [UE/Basic] 하드 레퍼런싱와 소프트 레퍼런싱 (0) | 2025.03.18 |
| [UE/Basic] FHitResult (0) | 2025.02.26 |
| [UE/Basic] 게임 콘텐츠 구조 (0) | 2025.02.10 |