Skip to content

Making Saves Cheap ​

Aegis Save is architected so that games which tell it what changed pay only for what changed. This guide explains how change detection works, why the default configuration is conservative, and how to use state revision counters to achieve sub-millisecond autosaves across 10,000+ actors.


1. The Dirty Fraction: Why Aegis Won't Guess ​

The single largest cost factor in any save system is serializing property reflection trees:

  • In a world with 10,000 persistent actors, if only 20 actors changed during the last 60 seconds of gameplay, serializing all 10,000 actors is a colossal waste of CPU.
  • However, Aegis will not guess whether an actor changed by hashing its properties in memory: serializing an actor to see if its bytes changed costs the exact serialization price you were trying to avoid!
  • Furthermore, guessing incorrectly in the cheap direction means a player loses progress.

Mandatory Disclosure (FO-15)

By default, Aegis Save operates in Automatic mode: it conservatively inspects every persistent actor on each save pass to guarantee player data is never lost. Making saves scale with what changed is something your game signals to Aegis, not a project settings slider.


2. The Cheap Signal: GetAegisStateRevision ​

The fastest and most elegant way to tell Aegis an actor is clean is by implementing IAegisPersistenceEvents::GetAegisStateRevision.

GetAegisStateRevision is a lightweight BlueprintNativeEvent:

  • Aegis invokes it on the actor during the capture walk.
  • It returns an integer (e.g. int32 RevisionCounter).
  • Aegis compares this integer against the revision it recorded at the last save.
  • If the revision matches, Aegis completely skips the entire property reflection walk!

C++ Implementation ​

Implement the interface on your actor:

cpp
#include "Identity/AegisPersistenceEvents.h"

UCLASS()
class AMyLootChest : public AActor, public IAegisPersistenceEvents
{
    GENERATED_BODY()

public:
    // Simply return your internal mutation revision counter
    virtual int32 GetAegisStateRevision_Implementation() const override
    {
        return ChestRevision;
    }

    void ModifyChestContents()
    {
        // Whenever state changes, bump the counter!
        ChestRevision++;
    }

private:
    UPROPERTY(SaveGame)
    int32 ChestRevision = 0;
};

Blueprint Implementation ​

  1. In your Actor Blueprint, click Class Settings in the toolbar.
  2. In the Details panel under Interfaces, click Add and choose Aegis Persistence Events.
  3. In the My Blueprint panel under Interfaces, double-click Get Aegis State Revision.
  4. Wire your integer variable (e.g., CurrentRevision) to the Return Value pin.

3. The Explicit Signal: MarkChanged ​

If you do not want to maintain a revision counter, you can manually flag an actor as dirty whenever it mutates:

text
[Mark Changed (Aegis)]
  └── Target: (Self)
cpp
#include "Core/AegisSubsystem.h"

UAegisSubsystem* Aegis = UAegisSubsystem::Get(this);
if (Aegis)
{
    Aegis->MarkChanged(this);
}

Calling MarkChanged immediately flags the actor as dirty, guaranteeing that it will be captured on the next save pass regardless of mode.


4. Change Detection Modes ​

On UAegisPersistenceComponent, you can set the Change Detection property:

ModeProperty Walk is Skipped WhenFallback Behavior
Automatic (Default)Object implements GetAegisStateRevision and revision is unchanged.Walks the actor. Guaranteed 100% correct, conservative default.
RevisionRevision counter is unchanged.Logs a warning if interface is missing and treats as Always.
ManualMarkChanged has not been called since the last save pass.You take full responsibility for signaling changes.
AlwaysNever skipped. Actor is captured on every save.Use for actors that mutate continuously every frame.

5. Performance Impact at Scale ​

Here is the real-world measured impact across a world with 10,000 persistent actors:

StrategyActors Walked per SaveAdded Frame Time (p99)CPU Overhead
Unoptimized (Full Walk)10,000 actors~4.0 msHigh
Optimized (GetAegisStateRevision)~200 actors (2% dirty)0.60 msNegligible (< 1.0 ms)

By supplying revision counters on your placed actors, you turn a multi-millisecond full world walk into a sub-millisecond incremental update!


Next Steps ​

Aegis Save — Enterprise World Persistence for Unreal Engine 5.