Schema Evolution & Migrations
As your game evolves across updates, DLCs, and balance patches, your actor classes and variable structures will change. If a player updates their game, their existing save files from Version 1.0 must load cleanly into Version 1.1.
Aegis Save provides a dedicated Schema Migration Framework (UAegisSchemaMigration) to handle property renames, structural shifts, and data transformations automatically.
1. Schema Versions & Metadata
Every save file stores a GameSchemaVersion in its metadata header:
FAegisSaveOptions Options;
Options.GameSchemaVersion = 2; // Incremented for Patch 1.1
UAegisSubsystem::Get(this)->SaveGame(TEXT("Slot01"), Options);When LoadGame is called:
- Aegis reads the file's
GameSchemaVersion. - If the file's schema version matches the current game version, properties load directly.
- If the file is from an older schema version, Aegis automatically executes the registered migration chain (
FromVersion$\rightarrow$ToVersion) before restoring actors.
2. Property Redirectors (Track A)
If you simply renamed a variable (e.g. Health $\rightarrow$ CurrentHealth) or moved a property to a different component, you do not need to write C++ migration code.
Use FAegisPropertyRedirect:
#include "Schema/AegisSchemaMigration.h"
UCLASS()
class UMyGameMigration_v1_to_v2 : public UAegisSchemaMigration
{
GENERATED_BODY()
public:
UMyGameMigration_v1_to_v2()
{
FromVersion = 1;
ToVersion = 2;
// Redirect Old Property Name -> New Property Name
FAegisPropertyRedirect HealthRedirect;
HealthRedirect.TargetClassName = TEXT("BP_PlayerCharacter_C");
HealthRedirect.OldPropertyName = TEXT("Health");
HealthRedirect.NewPropertyName = TEXT("CurrentHealth");
PropertyRedirects.Add(HealthRedirect);
}
};When loading a Version 1 save, Aegis automatically maps the stored Health tagged property bytes into the new CurrentHealth variable.
3. Custom Data Transformations (Track B)
If you made a structural change—such as converting an integer Gold into an itemized currency struct, or splitting one variable into two:
Override ApplyMigration in your UAegisSchemaMigration subclass:
bool UMyGameMigration_v1_to_v2::ApplyMigration_Implementation(FAegisMigrationContext& Context)
{
// Query records in the migration context:
for (FAegisRecordMigrationEntry& Entry : Context.Records)
{
if (Entry.TargetClassName == TEXT("BP_PlayerCharacter_C"))
{
// Read old raw property value
int32 OldGold = 0;
if (Entry.GetPropertyValue(TEXT("Gold"), OldGold))
{
// Create new structured currency entry
FCurrencyData NewCurrency;
NewCurrency.GoldCoins = OldGold;
NewCurrency.SilverCoins = 0;
Entry.SetPropertyValue(TEXT("PlayerCurrency"), NewCurrency);
Entry.RemoveProperty(TEXT("Gold"));
}
}
}
return true; // Return true to commit migration
}4. Atomic Abort on Failure (C-32)
Aegis Save guarantees Atomic Migration Safety:
- If a migration step encounters an unexpected failure and returns
false, the load is immediately aborted with result codeEAegisResult::MigrationFailed. - The partially migrated save is never written back to disk.
- The player's existing save file and current session remain 100% untouched and uncorrupted (AC-509 Verified).
Next Steps
- Review common customer issues in Troubleshooting & Diagnostics.