콘텐츠로 이동

UE5 UObject 직렬화와 Asset Pipeline

UE5는 FArchive를 통해 UObject를 바이너리로 직렬화합니다. UPROPERTY()로 마킹된 프로퍼티가 자동으로 직렬화됩니다.

UCLASS()
class UPlayerData : public UObject {
GENERATED_BODY()
UPROPERTY(SaveGame) // SaveGame 플래그: SaveGame 시스템에 포함
int32 Level = 1;
UPROPERTY(SaveGame)
float Experience = 0.f;
UPROPERTY() // SaveGame 없음: 에디터/패키지에만 직렬화
FString CharacterName;
int32 SessionScore = 0; // UPROPERTY 없음: 직렬화 안 됨
};

Serialize 함수를 오버라이드해 커스텀 직렬화 로직을 추가합니다.

UCLASS()
class UVersionedData : public UObject {
GENERATED_BODY()
UPROPERTY() int32 Version = 2;
UPROPERTY() FString Name;
UPROPERTY() TArray<float> Values;
virtual void Serialize(FArchive& Ar) override {
Super::Serialize(Ar);
// 버전에 따라 다른 직렬화
if (Ar.IsLoading() && Version < 2) {
// 구버전 데이터 마이그레이션
FString OldName;
Ar << OldName;
Name = OldName.ToUpper(); // 변환
}
}
};
// 파일에 쓰기
void SaveToFile(const FString& Path, const TArray<uint8>& Data) {
TUniquePtr<FArchive> Writer(IFileManager::Get().CreateFileWriter(*Path));
if (Writer) {
int32 Magic = 0xDEADBEEF;
*Writer << Magic;
int32 Count = Data.Num();
*Writer << Count;
for (uint8 Byte : Data)
*Writer << Byte;
}
}
// 파일에서 읽기
bool LoadFromFile(const FString& Path, TArray<uint8>& OutData) {
TUniquePtr<FArchive> Reader(IFileManager::Get().CreateFileReader(*Path));
if (!Reader) return false;
int32 Magic;
*Reader << Magic;
if (Magic != 0xDEADBEEF) return false;
int32 Count;
*Reader << Count;
OutData.SetNum(Count);
for (uint8& Byte : OutData)
*Reader << Byte;
return true;
}
// UObject → TArray<uint8>
TArray<uint8> SerializeObject(UObject* Obj) {
TArray<uint8> Buffer;
FMemoryWriter Writer(Buffer, true);
FObjectAndNameAsStringProxyArchive Ar(Writer, false);
Ar.ArIsSaveGame = true; // SaveGame 프로퍼티만 직렬화
Obj->Serialize(Ar);
return Buffer;
}
// TArray<uint8> → UObject
void DeserializeObject(UObject* Obj, const TArray<uint8>& Buffer) {
FMemoryReader Reader(Buffer, true);
FObjectAndNameAsStringProxyArchive Ar(Reader, false);
Ar.ArIsSaveGame = true;
Obj->Serialize(Ar);
}
// 런타임 DataTable 로드 (CSV 문자열)
UDataTable* CreateTableFromCSV(const FString& CSV) {
UDataTable* Table = NewObject<UDataTable>();
Table->RowStruct = FMyRowStruct::StaticStruct();
Table->CreateTableFromCSVString(CSV);
return Table;
}
#include "AssetRegistry/AssetRegistryModule.h"
void FindAllWeaponData() {
FAssetRegistryModule& Registry =
FModuleManager::LoadModuleChecked<FAssetRegistryModule>("AssetRegistry");
FARFilter Filter;
Filter.ClassPaths.Add(UWeaponData::StaticClass()->GetClassPathName());
Filter.bRecursiveClasses = true;
TArray<FAssetData> Assets;
Registry.Get().GetAssets(Filter, Assets);
for (const FAssetData& Asset : Assets) {
UWeaponData* Data = Cast<UWeaponData>(Asset.GetAsset());
if (Data) UE_LOG(LogTemp, Log, TEXT("Found: %s"), *Data->GetName());
}
}
  • UPROPERTY(SaveGame)으로 SaveGame에 포함할 프로퍼티 명시
  • Serialize(FArchive&) 오버라이드로 버전 마이그레이션 처리
  • FMemoryWriter/Reader + FObjectAndNameAsStringProxyArchive로 네트워크/DB 전송용 직렬화
  • Asset Registry로 런타임에 특정 클래스 에셋 전체 검색
  • ArIsSaveGame = true로 SaveGame 플래그 프로퍼티만 선택 직렬화