UnrealEngineでAActorやUObjectを継承したオブジェクトのデータの保存、読み込みをしていますが、UE5.3で作成したデータがUE5.5で読み込めなかったので対応しました。
その内容についてメモしておきます。
確認環境
- UE5.3.2
- UE5.5.4
オブジェクトデータの保存、読み込み
以下のようなC++を用意しておきます。
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "Serialization/ObjectAndNameAsStringProxyArchive.h"
#include "MyObject.generated.h"
struct MySaveGameArchive : public FObjectAndNameAsStringProxyArchive
{
MySaveGameArchive(FArchive& InInnerArchive)
: FObjectAndNameAsStringProxyArchive(InInnerArchive, true)
{
ArIsSaveGame = true;
ArNoDelta = true;
}
};
/**
*
*/
UCLASS()
class MEMORYWRITERTEST53_API UMyObject : public UObject
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable)
static TArray<uint8> SaveObejct(UObject* Object)
{
TArray<uint8> Data;
FMemoryWriter Writer(Data, true);
MySaveGameArchive MyArchive(Writer);
Object->Serialize(MyArchive);
return Data;
}
UFUNCTION(BlueprintCallable)
static void LoadObject(UObject* Object, const TArray<uint8>& Data)
{
FMemoryReader Reader(Data, true);
MySaveGameArchive MyArchive(Reader);
Object->Serialize(MyArchive);
}
UFUNCTION(BlueprintCallable)
static bool SaveDataToFile(const FString& FilePath, const TArray<uint8>& Data)
{
return FFileHelper::SaveArrayToFile(Data, *FilePath);
}
UFUNCTION(BlueprintCallable)
static bool LoadDataFromFile(const FString& FilePath, TArray<uint8>& Data)
{
return FFileHelper::LoadFileToArray(Data, *FilePath);
}
};
AActorやUObjectを継承するクラスでセーブ・ロードしたい変数のSaveGameをチェックしておきます。
以下のようにBlueprintで実行すれば、2番目のCostructしたObjectにも1番目に設定された値が再現できます。
SaveObject関数で得られたByte配列をSaveDataToFile関数でファイルに保存しておき、LoadDataFromFle関数で得られたByte配列をLoadObject関数に与えることもできます。
UE5.3で作成したデータがUE5.5で読めない
UE5.3においてSaveObject関数で得られたByte配列をSaveDataToFile関数でファイルに保存しておき、UE5.5においてoadDataFromFle関数で得られたByte配列をLoadObject関数に与えると値は読み込まれずに初期値のままです。
そこで、以下のようにLoadObject関数を変更することで値を読み込むことができました(同じUE5.5のデータなら変更なしで読み込み可能)。
データがいつの時点で作られたかのバージョンの指定が必要みたいです。
UE5.3の際のEUnrealEngineObjectUE5Versionを確認するとDATA_RESOURCESが最新でその値を設定しています。
UFUNCTION(BlueprintCallable)
static void LoadObject(UObject* Object, const TArray<uint8>& Data)
{
FMemoryReader Reader(Data, true);
// 以下の行追加
Reader.SetUEVer(FPackageFileVersion(static_cast<int>(EUnrealEngineObjectUE5Version::DATA_RESOURCES),
EUnrealEngineObjectUE5Version::DATA_RESOURCES));
MySaveGameArchive MyArchive(Reader);
Object->Serialize(MyArchive);
}