保存和加载游戏

蓝图实现

创建SaveGame对象

在新的 SaveGame 对象蓝图中,创建要保存所有信息的变量。

保存游戏

首先,使用 Create Save Game Object 节点,基于 SaveGame 类创建对象。

给 Save Game 实例中的 PlayerName 变量赋值。

完成 SaveGame 对象的赋值之后,利用 Save Game To Slot 节点完成保存游戏。

SlotName 为文件名,UserIndex 为用户 ID 。

保存游戏文件使用 .sav 扩展名,并在项目的 Saved\SaveGames 文件夹中显示。

加载游戏

要加载保存的游戏,需要提供保存时使用的插槽名和用户ID。

如果存在指定 SaveGame ,引擎将用其中数据填充 SaveGame 对象,并将其返回为 SaveGame(USaveGame类)基本对象。

然后可将该对象转换为自定义 SaveGame 类并访问数据。

异步方法

若有大量数据,或希望在加载时使用加载画面或动画,建议采用异步方法。同步方法主要用于快速加载小型数据。

Async Load Game From SlotAsync Save Game to Slot 节点具有两个执行输出引脚。

操作开始时将执行第一个引脚,操作完成时则执行第二个引脚,执行第二引脚前变量输出引脚无效。

Success 引脚可表示操作是否成功。

C++实现

创建SaveGame对象

MySaveGame.h

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/SaveGame.h"
#include "MySaveGame.generated.h"

/**
 * 
 */
UCLASS()
class SAVEANDLOADGAME_API UMySaveGame : public USaveGame
{
	GENERATED_BODY()

public:

	UPROPERTY(VisibleAnywhere, Category = Basic)
	FString PlayerName;
	
};

保存游戏

异步保存

推荐使用 AsyncSaveGameToSlot 保存游戏。使用异步可防止帧率突然卡帧,使玩家不易觉察,并避免某些平台上出现认证问题。

if (UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass())))
{
	//设置委托
	FAsyncSaveGameToSlotDelegate SaveDelegate;

	//设置SaveGame对象上的数据
	SaveGameInstance->PlayerName = TEXT("AsyncPlayer");

	//启动异步保存进程
	UGameplayStatics::AsyncSaveGameToSlot(SaveGameInstance, TEXT("AsyncCPPSave"), 0, SaveDelegate);

	UE_LOG(LogTemp, Warning, TEXT("AsyncSave Success"));
}

同步保存

SaveGameToSlot 足以应对小型SaveGame格式,暂停时或在菜单中即可保存游戏。

if (UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass())))
{
	//设置SaveGame对象上的数据
	SaveGameInstance->PlayerName = TEXT("SyncPlayer");

	//保存游戏
	if (UGameplayStatics::SaveGameToSlot(SaveGameInstance, TEXT("SyncCPPSave"), 0))
	{
		//成功保存
		UE_LOG(LogTemp, Warning, TEXT("SyncSave Success"));
	}
}

二进制保存

SaveGameToMemory 函数将 SaveGame 对象传输到内存,函数仅支持同步操作,但快于保存到驱动器。

函数调用将提供存储数据缓冲区(TArray&)的引用。

成功时,函数返回true。

TArray<uint8> SaveData;
UMySaveGame* SaveGameInstance = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()));
SaveGameInstance->PlayerName = TEXT("BinaryPlayer");
if (UGameplayStatics::SaveGameToMemory(SaveGameInstance, SaveData))
{
	// 操作成功,SaveData现在包含SaveGame对象的二进制代表。
	if (UGameplayStatics::SaveDataToSlot(SaveData, TEXT("BinaryCPPSave"), 0))
	{
		// 操作成功,已将SaveData写入到存档文件。
		UE_LOG(LogTemp, Warning, TEXT("BinarySave Success"));
	}
}

加载游戏

异步加载

AsyncLoadGameFromSlot 执行异步加载时,必须提供回调委托,以接收系统加载的数据。

//设置委托
FAsyncLoadGameFromSlotDelegate LoadedDelegate;

LoadedDelegate.BindUObject(this, &ABasePlayer::LoadGameDelegateFunction);

UGameplayStatics::AsyncLoadGameFromSlot(TEXT("AsyncCPPSave"), 0, LoadedDelegate);

同步加载

若成功,LoadGameFromSlot 函数将创建并返回 USaveGame 对象。

//查找并将USaveGame对象转换成UMySaveGame
if (UMySaveGame* LoadedGame = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("SyncCPPSave"), 0)))
{
	UE_LOG(LogTemp, Warning, TEXT("SyncLoad: %s"), *LoadedGame->PlayerName);
}

二进制加载

LoadDataFromSlot 以原始二进制格式加载 SaveGame 数据,同步操作尽可用于此类加载。

LoadGameFromMemory 函数将二进制数据转换为 SaveGame 对象,函数为同步调用,成功时返回新的 USaveGame 对象,失败时返回空指针。

TArray<uint8> OuterSaveData;
if (UGameplayStatics::LoadDataFromSlot(OuterSaveData, TEXT("BinaryCPPSave"), 0))
{
	if (UMySaveGame* BinarySaveGame = Cast<UMySaveGame>(UGameplayStatics::LoadGameFromMemory(OuterSaveData)))
	{
		UE_LOG(LogTemp, Warning, TEXT("BinaryLoad: %s"), *BinarySaveGame->PlayerName);
	}
}

源码

posted @ 2020-06-28 10:42  CodeWithMe  阅读(1736)  评论(0)    收藏  举报