UE5 UObject 직렬화와 Asset Pipeline
UE5 직렬화 개요
섹션 제목: “UE5 직렬화 개요”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(); // 변환 } }};FArchive 직접 사용
섹션 제목: “FArchive 직접 사용”// 파일에 쓰기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를 바이트 배열로 직렬화
섹션 제목: “UObject를 바이트 배열로 직렬화”// 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> → UObjectvoid DeserializeObject(UObject* Obj, const TArray<uint8>& Buffer) { FMemoryReader Reader(Buffer, true); FObjectAndNameAsStringProxyArchive Ar(Reader, false); Ar.ArIsSaveGame = true; Obj->Serialize(Ar);}DataTable CSV/JSON 임포트
섹션 제목: “DataTable CSV/JSON 임포트”// 런타임 DataTable 로드 (CSV 문자열)UDataTable* CreateTableFromCSV(const FString& CSV) { UDataTable* Table = NewObject<UDataTable>(); Table->RowStruct = FMyRowStruct::StaticStruct(); Table->CreateTableFromCSVString(CSV); return Table;}Asset Registry로 에셋 검색
섹션 제목: “Asset Registry로 에셋 검색”#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 플래그 프로퍼티만 선택 직렬화