Serialization in Unreal Engine

1. What is Serialization?

Serialization is the process of converting an object or data structure into a format that can be easily stored or transmitted, and subsequently reconstructed. In Unreal Engine, serialization is often used for:

2. UE4/UE5 Serialization System

Unreal Engine uses several classes and methods for serialization, built around Unreal's reflection system. The core class for serialization is FArchive, which provides the basic interface for reading and writing data.

Key Classes and Concepts:

3. Basic Serialization Example

Let’s start with a simple example of serializing a custom struct to a binary format.

// Define a simple struct
USTRUCT(BlueprintType)
struct FMyStruct
{
    GENERATED_BODY()

    UPROPERTY()
    int32 MyInt;

    UPROPERTY()
    float MyFloat;

    UPROPERTY()
    FString MyString;

    // Implement custom serialization
    friend FArchive& operator<<(FArchive& Ar, FMyStruct& MyStruct)
    {
        Ar << MyStruct.MyInt;
        Ar << MyStruct.MyFloat;
        Ar << MyStruct.MyString;
        return Ar;
    }
};

// Serializing the struct to a file
void SaveStructToFile(const FString& FilePath, const FMyStruct& Data)
{
    // Create a binary archive writer
    FBufferArchive Archive;
    Archive << const_cast<FMyStruct>(Data);

    // Write to disk
    if (FFileHelper::SaveArrayToFile(Archive, *FilePath))
    {
        UE_LOG(LogTemp, Log, TEXT("Saved successfully!"));
    }
    Archive.FlushCache();
    Archive.Empty();
}

// Deserializing the struct from a file
bool LoadStructFromFile(const FString& FilePath, FMyStruct& Data)
{
    TArray<uint8> BinaryArray;
    if (FFileHelper::LoadFileToArray(BinaryArray, *FilePath))
    {
        FMemoryReader FromBinary = FMemoryReader(BinaryArray, true); // true: Free binary array after read
        FromBinary.Seek(0);
        FromBinary << Data;
        FromBinary.FlushCache();
        BinaryArray.Empty();
        return true;
    }
    return false;
}

4. Advanced Serialization Techniques

4.1. Serializing UObjects

For UObjects, Unreal’s Serialize function is used. This method is automatically called for UObjects when you serialize them using an archive. You can override this function in your custom classes to handle specific serialization logic.

class UMyObject : public UObject
{
    GENERATED_BODY()

public:
    UPROPERTY()
    int32 MyInt;

    UPROPERTY()
    FString MyString;

    virtual void Serialize(FArchive& Ar) override
    {
        Super::Serialize(Ar);

        Ar << MyInt;
        Ar << MyString;
    }
};

4.2. Custom Serialization Formats

If you need to serialize to a custom format (e.g., XML, JSON, or a proprietary binary format), you’ll use a combination of FArchive or FStructuredArchive, custom parsers, and serialization functions.

Example: JSON Serialization

// JSON Serialization Example
void SerializeToJson(const FString& FilePath, const FMyStruct& Data)
{
    TSharedPtr<FJsonObject> JsonObject = MakeShareable(new FJsonObject);
    JsonObject->SetNumberField(TEXT("MyInt"), Data.MyInt);
    JsonObject->SetNumberField(TEXT("MyFloat"), Data.MyFloat);
    JsonObject->SetStringField(TEXT("MyString"), Data.MyString);

    FString OutputString;
    TSharedRef<TJsonWriter<>> Writer = TJsonWriterFactory<>::Create(&OutputString);
    FJsonSerializer::Serialize(JsonObject.ToSharedRef(), Writer);

    FFileHelper::SaveStringToFile(OutputString, *FilePath);
}

bool DeserializeFromJson(const FString& FilePath, FMyStruct& Data)
{
    FString JsonString;
    if (FFileHelper::LoadFileToString(JsonString, *FilePath))
    {
        TSharedRef<TJsonReader<>> Reader = TJsonReaderFactory<>::Create(JsonString);
        TSharedPtr<FJsonObject> JsonObject;
        if (FJsonSerializer::Deserialize(Reader, JsonObject) && JsonObject.IsValid())
        {
            Data.MyInt = JsonObject->GetIntegerField(TEXT("MyInt"));
            Data.MyFloat = JsonObject->GetNumberField(TEXT("MyFloat"));
            Data.MyString = JsonObject->GetStringField(TEXT("MyString"));
            return true;
        }
    }
    return false;
}

5. Best Practices

6. Conclusion

Serialization in Unreal Engine is a powerful tool that allows developers to save and restore game states, transmit data over the network, and more. By leveraging Unreal's serialization system and following best practices, you can create efficient and maintainable systems for managing your game's data. Always keep in mind the specific needs of your project when choosing the serialization approach, whether it's binary, JSON, or a custom format.