Course contentsShow
← Unreal Engine Game Development
Lesson 196 of 8803. C++ and UObject ArchitectureFree lesson

Serializing Complex Data Structures for Save Games

Apply the reflection system to serialize custom UStructs and UObjects, enabling persistent state management and robust save-game functionality in your projects.

In this lesson, you will learn how to leverage Unreal’s reflection system to transform your custom game data into a format that persists between play sessions.

The Role of Reflection in Serialization

Serialization is the process of converting an object's state into a stream of data that can be written to disk. In Unreal Engine, we don't have to manually write every variable to a file; instead, we rely on the Reflection System. By tagging our variables with the UPROPERTY() macro, we tell the engine’s "data scanner" exactly which pieces of information are part of the object’s identity.

When you create a USaveGame object, the engine uses this reflection data to automatically iterate through your USTRUCTs and UOBJECTs. If a variable is marked as a UPROPERTY, the engine knows how to encode it, allowing you to save complex states with minimal boilerplate code.

Applying Serialization to Custom Data

Imagine you have a complex player profile. You can define this as a USTRUCT so that it can be easily stored within a USaveGame instance.

USTRUCT(BlueprintType)
struct FPlayerSaveData
{
    GENERATED_BODY()

    UPROPERTY()
    int32 ExperiencePoints;

    UPROPERTY()
    FString PlayerName;

    UPROPERTY()
    TArray<FString> InventoryItems;
};

By marking these members with UPROPERTY(), you ensure the serialization system recognizes them. If you were to omit the macro, the reflection system would ignore those variables, and they would reset to default values every time you loaded your game.

Managing Complex Graphs

When serializing UObjects, remember that the engine handles the "graph" automatically. If your save object holds a pointer to a UObject, the serialization process will recursively follow that reference to save the object’s state, provided that the object itself is properly marked with the UCLASS macro and its internal members are marked with UPROPERTY.

To maintain a robust save system, ensure that your data structures remain "flat" where possible and avoid complex circular references, which we previously discussed as being difficult for the garbage collector—they can also create significant overhead for the serializer.

Key Takeaway: Use the UPROPERTY() macro on all variables within your USTRUCTs and UOBJECTs to ensure the reflection system can automatically discover and persist your game data during save operations.