Skip to content

Destroyed Actors & Tombstones ​

In game development, handling actor destruction across save files is one of the most deceptively complex architectural problems. If not handled correctly, defeated bosses respawn, looted chests close, and player save files bloat uncontrollably.

This guide details Aegis Save's Tombstone Reconciliation Engine and explains how to prevent duplicate death and loot events.


1. Why Simple Record Erasure Fails (R-10) ​

When a player destroys a level-placed actor (e.g., defeats an elite enemy or destroys a wooden barricade), a naive save system simply deletes that actor's record from the save file.

The Respawn Defect ​

  1. Level contains Placed_Enemy_01 baked into the map package.
  2. Player kills the enemy. Naive save deletes the enemy's record from the save file.
  3. Player saves and reloads the game.
  4. Unreal Engine loads the map package from disk. Because the map package contains Placed_Enemy_01, the enemy spawns back into the world at full health!
text
[Naïve Erasure Trap]
Enemy Killed ──► Record Deleted from Save ──► Level Reloaded ──► Placed Actor Spawns Fresh! (BUG)

2. The Tombstone Solution (R-10) ​

Aegis Save solves this through Tombstone Records:

text
[Aegis Tombstone Engine]
Enemy Killed ──► Recorded as Tombstone ──► Level Reloaded ──► Placed Actor Cleaned Up! (CORRECT)
  • When a level-placed actor with UAegisPersistenceComponent is destroyed during gameplay, Aegis writes an explicit Tombstone Record to the save container.
  • On save load, before player gameplay begins, Aegis inspects the world. Any resident actor whose identity matches a tombstone is immediately removed (WasDestroyedByLoad = true).
  • The defeated enemy stays dead, and opened chests stay looted!

3. Runtime Spawned Actors: Unbounded Bloat Prevention (R-12) ​

While level-placed actors require tombstones to prevent the map file from respawning them, runtime-spawned actors do not:

  • Spawned actors (dropped loot, spawned projectiles, temporary minions) are not in the map file.
  • If every destroyed spawned goblin left a tombstone, a 50-hour RPG save file would accumulate tens of thousands of dead records, bloating save file size and memory.

Aegis Automatic Differentiation (R-12) ​

  • Placed Actors: Tombstoned on destruction (bounded by level actor count).
  • Spawned Actors (created via SpawnPersistentActor or marked via SetIsRuntimeSpawned): Erased completely on destruction.
  • Saves remain tiny and load times remain blistering fast throughout 100+ hour playthroughs.

4. The WasDestroyedByLoad Lifecycle Guard ​

When Aegis loads a save and removes an actor that was previously destroyed, Unreal Engine fires AActor::EndPlay(EEndPlayReason::Destroyed).

To the engine, this destruction looks identical to the actor being killed by the player in live gameplay!

The Duplicate Loot & Sound Hazard

If your chest or enemy spawns loot drops, awards XP, or plays a death explosion inside EndPlay, it will trigger again every time the player loads their save!

Guarding Gameplay Logic ​

Always check WasDestroyedByLoad inside EndPlay:

text
[Event End Play]
       │
       ▼
[Was Destroyed By Load (Aegis)]
       │
       ▼
   [Branch]
   ├── True  ──► (Actor was destroyed by save load; SKIP LOOT & AUDIO!)
   └── False ──► [Award Player XP] ──► [Spawn Loot Item] ──► [Play Death FX]
cpp
void AMyEnemyCharacter::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
    Super::EndPlay(EndPlayReason);

    UAegisSubsystem* Aegis = UAegisSubsystem::Get(this);
    if (Aegis && Aegis->WasDestroyedByLoad(this))
    {
        // This actor is being cleaned up because the loaded save records it as dead.
        // DO NOT spawn loot, DO NOT award XP, DO NOT play sounds!
        return;
    }

    // Legit gameplay kill:
    AwardExperiencePoints();
    SpawnDeathLoot();
    PlayDeathScream();
}

Summary Matrix ​

Actor TypeCreation MethodOn Destruction During PlayOn Save Load
Level-Placed ActorAuthored in Level EditorWrites Tombstone (R-10)Destroyed via WasDestroyedByLoad
Runtime Spawned ActorSpawnPersistentActorErased from Store (R-12)Not recreated (stays absent)
Unregistered ActorStandard SpawnActorIgnored by AegisIgnored by Aegis

Next Steps ​

Aegis Save — Enterprise World Persistence for Unreal Engine 5.