SaveGame存儲系統
使用SaveGame存儲遊戲到本地的邏輯和方法都很簡單,涉及兩個部分SaveGame對象,以及存儲、加載方法。下面我們一一講解。
一、SaveGame對象
首先,我們要創建一個繼承USaveGame的類。我們需要在這個類的實例中保存需要持久化到磁盤的遊戲數據,然後調用存儲方法,將其寫入磁盤。所以,我們在自定義USaveGame類中聲明需要持久化的變量。一般,這些變量最好加個BlueprintReadWrite的宏,這樣,我們也可以在藍圖中對這些變量進行修改或讀取。
其實,到這裏,這個類的基本介紹就完了。- - 其實,這個類就是將我們的對象序列化保存,然後反序列化到對象。
下面給出ActionRPG中的示例
namespace ERPGSaveGameVersion
{
enum type
{
//初始化版本
Initial,
//揹包修改
AddedInventory,
//物品修改
AddedItemData,
VersionPlusOne,
//最新版本
LatestVersion = VersionPlusOne - 1
};
}
UCLASS(BlueprintType)
class ACTIONRPG_API URPGSaveGame : public USaveGame
{
GENERATED_BODY()
public:
URPGSaveGame()
{
//當新創建一個SaveGame對象時,默認構造器會將其設置爲最新版本
SavedDataVersion = ERPGSaveGameVersion::LatestVersion;
}
/** Map of items to item data */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = SaveGame)
TMap<FPrimaryAssetId, FRPGItemData> InventoryData;
/** Map of slotted items */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = SaveGame)
TMap<FRPGItemSlot, FPrimaryAssetId> SlottedItems;
/** 玩家的唯一ID */
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = SaveGame)
FString UserId;
protected:
/** Deprecated way of storing items, this is read in but not saved out */
UPROPERTY()
TArray<FPrimaryAssetId> InventoryItems_DEPRECATED;
//當前SaveGame對象版本
UPROPERTY()
int32 SavedDataVersion;
/** 可以對SaveGame對象進行維護 */
virtual void Serialize(FArchive& Ar) override;
};
void URPGSaveGame::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
if (Ar.IsLoading() && SavedDataVersion != ERPGSaveGameVersion::LatestVersion)
{
if (SavedDataVersion < ERPGSaveGameVersion::AddedItemData)
{
// Convert from list to item data map
for (const FPrimaryAssetId& ItemId : InventoryItems_DEPRECATED)
{
InventoryData.Add(ItemId, FRPGItemData(1, 1));
}
InventoryItems_DEPRECATED.Empty();
}
SavedDataVersion = ERPGSaveGameVersion::LatestVersion;
}
}
二、存儲、加載方法
UGameplayStatics中提供了幾個靜態方法,可以方便我們存儲與加載序列化的SaveGame。
方法 | 說明 |
---|---|
bool UGameplayStatics::DoesSaveGameExist(FString SlotName, int32 UserIndex) | 指定SaveGame對象是否存在。 SlotName爲存儲對象的一個標識符,可以通過不同的標識符來獲取不同的存儲對象,UserIndex爲玩家索引 |
USaveGame* UGameplayStatics::LoadGameFromSlot(FString SlotName, int32 UserIndex) | 加載指定SaveGame對象。 |
USaveGame* UGameplayStatics::CreateSaveGameObject(UClass* SaveGameClass) | 創建一個新的SaveGame對象。參數爲SaveGame類的元數據 |
bool UGameplayStatics::SaveGameToSlot(USaveGame* SaveGame,int32 UserIndex) | 保存SaveGame對象到本地。 |
下面給出ActionRPG中的示例
bool URPGGameInstanceBase::LoadOrCreateSaveGame()
{
// 將SaveGame對象設爲nullptr,則原來的SaveGame如果有效的話也將被GC
CurrentSaveGame = nullptr;
//判斷當前SaveGame對象在本地是否有副本(是否保存到本地過),並且允許保存
if (UGameplayStatics::DoesSaveGameExist(SaveSlot, SaveUserIndex) && bSavingEnabled)
{ //從本地加載SaveGame對象
CurrentSaveGame = Cast<URPGSaveGame>(UGameplayStatics::LoadGameFromSlot(SaveSlot, SaveUserIndex));
}
//如果當前SaveGame對象有效
if (CurrentSaveGame)
{
//設置揹包物品
AddDefaultInventory(CurrentSaveGame, false);
//如果從本地加載成功,返回true
return true;
}
else
{
//如果磁盤沒有副本,或者從磁盤加載失敗,將創建一個新的SaveGame對象
CurrentSaveGame = Cast<URPGSaveGame>(UGameplayStatics::CreateSaveGameObject(URPGSaveGame::StaticClass()));
//設置揹包物品
AddDefaultInventory(CurrentSaveGame, true);
//如果當前SaveGame對象爲新創建,將返回false
return false;
}
}