游戏缓存与加载
2024年4月20日 2024年4月22日
USaveGame
存档,读档。
惯例,先上文档链接
USaveGame是UObject的派生类,当我们需要缓存一个UObject对象时,使对象类型派生自USaveGame
头文件
1#include "GameFramework/SaveGame.h"
创建UObject对象和USaveGame对象的区别
-
创建UObject对象
1// UTestObject派生自UObject 2UTestObject *Obj = NewObject<UTestObject>();
-
创建USaveGame对象
1#include "Kismet/GameplayStatics.h" 2 3// UTestSaveGame派生自USaveGame 4UTestSaveGame *SaveGame = Cast<UTestSaveGame>(UGameplayStatics::CreateSaveGameObject(UTestSaveGame::StaticClass());
异步缓存
SaveSlotName和UnserIndex是USaveGame逻辑相关的,作为派生类的数据成员,在执行存/读档操作时使用
其中,UserIndex我只用了0,SaveSlotName用以缓存的标识,以及缓存文件的名称
1UCLASS() 2class [PROJECTNAME]_API UMySaveGame : public USaveGame 3{ 4 GENERATED_BODY() 5 6public: 7 UPROPERTY(VisibleAnywhere, Category = Basic) 8 FString SaveSlotName; 9 10 UPROPERTY(VisibleAnywhere, Category = Basic) 11 uint32 UserIndex; 12 13 //... 14};
异步操作即订阅委托,在缓存结束后收到通知
-
纯C++委托
-
回调函数声明
通过SlotName和UserIndex确定缓存为何1void CallFunc(const FString &SlotName, const int32 UserIndex, bool bSuccess);
-
注意到,绑定回调函数时,回调函数作为指针类型的成员函数
-
同样,回调函数的执行不在主进程
1UMySaveGame* SaveGameObj = Cast<UMySaveGame>(UGameplayStatics::CreateSaveGameObject(UMySaveGame::StaticClass()))); 2if (SaveGameObj) 3{ 4 FAsyncSaveGameToSlotDelegate SavedDelegate; 5 // USomeUObjectClass *SomeUObjectPointer; 6 SavedDelegate.BindUObject(SomeUObjectPointer, &USomeUObjectClass::SaveGameDelegateFunction); 7 UGameplayStatics::AsyncSaveGameToSlot(SaveGameObj, SaveSlotName, UserIndex, SavedDelegate); 8}
确实有对应的缓存文件
[项目路径]/Saved/SaveGame/[SaveSlotName].sav
异步加载
同样,订阅委托,在加载结束后收到通知
-
回调函数声明
1void CallFunc(const FString &SlotName, const int32 UserIndex, USaveGame *LoadedGameData);
-
此时,回调函数的第三个参数为USaveGame派生类对象,所需参数自行取出
1FAsyncLoadGameFromSlotDelegate LoadedDelegate; 2LoadedDelegate.BindUObject(SomeUObjectPointer, &USomeUObjectClass::LoadGameDelegateFunction); 3UGameplayStatics::AsyncLoadGameFromSlot(SlotName, UserIndex, LoadedDelegate);
注意
USaveGame只缓存使用UPROPERTY宏标记了的数据成员