Using Loaded Data: State vs. Visuals (From 0 to End)
The single most common question developers and artists ask when integrating a save system is:
"If a player opens a door and saves the game, when they reload or resume, will the door still be open? How does my actor actually USE the loaded data to update its 3D visuals and animations?"
Understanding the answer requires understanding the fundamental rule of Unreal Engine game architecture:
Separate Data State from Visual Representation.
This guide walks you through the complete lifecycle from Step 0 to the very end, showing you exactly how data flows from a save file into 3D meshes, animations, sounds, and UI.
1. The Core Concept: Data State vs. Visuals
When Aegis Save loads a file, it deserializes values directly into your variables in memory:
bIsOpen = trueCurrentHealth = 45.0RemainingAmmo = 8
However, Unreal Engine does not automatically rotate meshes, play timelines, or update HUD widgets just because a boolean variable changed in memory.
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ Data State │ │ Visual Representation │
│ (What Aegis Restores) │ │ (What the Player Sees) │
├──────────────────────────────┤ ├──────────────────────────────┤
│ • bIsOpen = true │ ──(You Link)►│ • Door Mesh rotated at 90° │
│ • CurrentHealth = 45.0 │ │ • Red Health Bar at 45% │
│ • bIsLit = false │ │ • Campfire particles disabled│
└──────────────────────────────┘ └──────────────────────────────┘Aegis Save guarantees that your data is 100% restored before your actor's first gameplay tick (AC-303).
Your Blueprint or C++ code simply links the restored variable to your mesh or timeline.
2. The Complete 0-to-End Walkthrough: Interactive Door
Let's follow an interactive dungeon door (BP_DungeonDoor) through its complete lifespan:
Step 0: Authoring the Actor
- Create an Actor Blueprint
BP_DungeonDoor. - Add a
StaticMeshComponentfor the Door Frame (Root Component). - Add a child
StaticMeshComponentfor the Door Slab (the moving door). - Add
UAegisPersistenceComponentto the actor. - In My Blueprint, create a boolean variable:
- Name:
bIsOpen - Advanced Details: Check
SaveGame(This tells Aegis to save this variable).
- Name:
Step 1: During Gameplay (Player Opens the Door)
When the player approaches the door and presses E:
- The interaction event runs.
- Set
bIsOpen = true. - Play a Timeline that smoothly rotates the Door Slab from 0° to 90°.
- Play a creaking wood audio cue and spawn dust particles.
- The door is now visually and logically open.
Step 2: Saving the Game
- The player reaches an autosave trigger or clicks "Save Game".
- Aegis inspects the door actor.
- Aegis reads
bIsOpen = trueand writes it into the compressed binary save container under the door's permanent GUID identity.
Step 3: What Happens on Load? (The 2 Loading Scenarios)
In Unreal Engine, a load happens in one of two distinct environments:
Scenario A: Level Open / Map Transition (e.g. Loading from Main Menu)
When the player clicks "Continue" in the Main Menu:
- Unreal Engine loads the level map package from disk.
- The door actor spawns into the world.
- During component registration, Aegis detects the door's GUID, reads its saved record from memory, and applies
bIsOpen = truebefore the actor's first tick (AC-303)! Event BeginPlayexecutes on the door.- How the door updates visually: Inside
BeginPlay, your Blueprint checksbIsOpen. Because Aegis already restored it,bIsOpenistrue! Your code immediately sets the Door Slab rotation to 90°.- Result: When the player opens their eyes in the level, the door is already open. No snapping, no popping, no delayed animation!
Scenario B: In-Place Checkpoint Reload (e.g. Player Dies Mid-Game)
When the player dies and you reload a checkpoint without reloading the level map:
- The door actor is already alive in the world.
BeginPlaywill never run again! - The game calls
Load Game from Slot. - Aegis matches live actors in the world and overwrites their variables with the checkpoint values (e.g., if the door was closed at the checkpoint,
bIsOpenis set back tofalse). - How the door updates visually: Aegis automatically invokes the
OnAegisPostLoadevent on the actor! InsideOnAegisPostLoad, your Blueprint reads the updatedbIsOpenvariable and snaps the door slab back to 0°.- Result: The door instantly closes in-place in under 10 milliseconds without any loading screen!
3. The Universal 3-Point Visual Pattern
To handle both Level Opens and In-Place Checkpoint Reloads flawlessly without duplicating logic or playing loud sounds during loading, use this simple 3-point pattern:
┌─────────────────────────────────────────────────────────────┐
│ Function: UpdateDoorVisuals │
│ Input: bInstant (Boolean) │
└──────────────────────────────┬──────────────────────────────┘
│
┌──────────────────┴──────────────────┐
▼ ▼
[bInstant == true] [bInstant == false]
(Used on Load / BeginPlay) (Used during Player Interaction)
│ │
▼ ▼
• Snap Slab Rotation to 90° • Play Smooth Timeline (0° to 90°)
• NO Audio Cue! • Play Creaking Audio Cue
• NO Particle Effects! • Spawn Dust ParticlesComplete Blueprint Wiring
[Event On Player Interact]
│
▼
[Set bIsOpen = NOT bIsOpen]
│
▼
[UpdateDoorVisuals (bInstant = false)] ──► Plays timeline, sound & FX smoothly!
[Event BeginPlay]
│
▼
[UpdateDoorVisuals (bInstant = true)] ──► Snaps pose immediately on map open!
[Event On Aegis Post Load] (From Aegis Persistence Events Interface)
│
▼
[UpdateDoorVisuals (bInstant = true)] ──► Snaps pose on in-place checkpoint reload!4. How to Implement the Aegis Persistence Events Interface
To receive the OnAegisPostLoad callback in Blueprint or C++:
In Blueprint:
- Open your Actor Blueprint (
BP_DungeonDoor). - In the toolbar, click Class Settings.
- In the Details panel on the right, find Interfaces $\rightarrow$ Implemented Interfaces.
- Click Add and select
Aegis Persistence Events. - In your My Blueprint panel under Interfaces, double-click
On Aegis Post Load(or right-click in the event graph and addEvent On Aegis Post Load). - Connect it directly to your
UpdateDoorVisuals (bInstant = true)function!
In C++:
Implement IAegisPersistenceEvents on your actor class:
// DungeonDoor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Identity/AegisPersistenceComponent.h"
#include "Identity/AegisPersistenceEvents.h"
#include "DungeonDoor.generated.h"
UCLASS()
class YOURGAME_API ADungeonDoor : public AActor, public IAegisPersistenceEvents
{
GENERATED_BODY()
public:
ADungeonDoor();
protected:
virtual void BeginPlay() override;
// --- IAegisPersistenceEvents Interface ---
virtual void OnAegisPostLoad_Implementation() override;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<UStaticMeshComponent> DoorFrameMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<UStaticMeshComponent> DoorSlabMesh;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly)
TObjectPtr<UAegisPersistenceComponent> Persistence;
UPROPERTY(EditAnywhere, BlueprintReadWrite, SaveGame, Category = "Door")
bool bIsOpen = false;
void UpdateVisuals(bool bInstant);
};
// DungeonDoor.cpp
#include "DungeonDoor.h"
ADungeonDoor::ADungeonDoor()
{
DoorFrameMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Frame"));
RootComponent = DoorFrameMesh;
DoorSlabMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Slab"));
DoorSlabMesh->SetupAttachment(RootComponent);
Persistence = CreateDefaultSubobject<UAegisPersistenceComponent>(TEXT("Persistence"));
Persistence->SetScope(EAegisScope::World);
}
void ADungeonDoor::BeginPlay()
{
Super::BeginPlay();
// 1. On Level Open: Aegis has already restored bIsOpen before BeginPlay (AC-303).
// Apply visual state instantly without sound or delay.
UpdateVisuals(/*bInstant=*/ true);
}
void ADungeonDoor::OnAegisPostLoad_Implementation()
{
// 2. On In-Place Reload: Checkpoint reloads update live actors without BeginPlay.
// Apply visual state instantly!
UpdateVisuals(/*bInstant=*/ true);
}
void ADungeonDoor::UpdateVisuals(bool bInstant)
{
const FRotator TargetRotation = bIsOpen ? FRotator(0.f, 90.f, 0.f) : FRotator::ZeroRotator;
if (bInstant)
{
// Snap immediately, no audio, no timeline
DoorSlabMesh->SetRelativeRotation(TargetRotation);
}
else
{
// Play smooth timeline animation + sound cue
// (e.g. trigger timeline component or play sound at location)
}
}5. What About Audio, Particles, and Death Effects?
A common pitfall in save systems is the "Deafening Reload":
If you have 40 torches and 15 doors in a level, and their visual update logic plays a sound effect, loading a save will play 55 sound cues at the exact same instant!
The Golden Rules for Clean Loading:
- Never play Sound Cues or Spawn Emitters inside
BeginPlayorOnAegisPostLoad. Always gate sound and particle effects behindbInstant == false(or player interaction events). - Use
WasDestroyedByLoadfor Destroyed Actors:
If an enemy or destructible chest spawns death particles or drops loot inAActor::EndPlay:text[Event End Play] ──► [Was Destroyed By Load (Aegis)] ──► Branch ├── True: Do nothing (actor was dead in the save) └── False: Spawn Loot & Play Death VFX (normal gameplay kill)
6. Updating UI (Health Bars, Ammo, Quest HUD) on Load
Just like 3D world actors, your Screen UI / UMG HUD needs to reflect loaded player stats.
Method 1: On Player Pawn OnAegisPostLoad
When your Player Character receives OnAegisPostLoad:
[Event On Aegis Post Load] (Inside BP_PlayerCharacter)
│
▼
[Get Player HUD Widget] ──► [Update Health Bar (CurrentHealth / MaxHealth)]
──► [Update Ammo Counter (CurrentAmmo)]Method 2: Subsystem Global Delegate (OnLoadCompleted)
Your HUD Widget can bind to the global subsystem delegate on construction:
[Event Construct] (Inside WBP_GameHUD)
│
▼
[Get Aegis Subsystem] ──► [Assign On Load Completed]
│
▼
[Event: HandleLoadCompleted]
│
▼
[Refresh All HUD Elements]Summary Checklist
To make any actor visually and mechanically react to loaded data:
- [x] Variable marked with
SaveGame. - [x] Create an
UpdateVisuals(bInstant)function. - [x] Call
UpdateVisuals(true)inEvent BeginPlay(for level opens & stream-ins). - [x] Implement
Aegis Persistence Eventsand callUpdateVisuals(true)inEvent On Aegis Post Load(for in-place checkpoint reloads). - [x] Gate sound cues, dust particles, and smooth timelines behind
bInstant == false.
Next Steps
- Build a complete interactive door in Recipe: Interactive Sliding/Rotating Door.
- See how container inventories and loot drops work in Recipe 1: Interactive Loot Chest.
- Learn about seamless level transitions in Complete Game Flow & Level Transitions.