【UE4】SaveGame存儲系統

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;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章