Persistence adapter

Capture and apply persistent world state through your own SaveGame, with deferred restore, schema versioning, optional migration and per-record reporting.

WSRF Core is a persistence adapter, not a SaveGame system

It provides no slots, no files, no autosave, no cloud storage and no save UI. It hands your project a versioned block of pure world-state data, and your existing save solution stores it. The optional Rest Site module additionally provides a WSRF-only Quick Save slot and a Blueprint-ready pure-data envelope for a project-owned USaveGame — it does not turn Core snapshots into a universal game SaveGame.

Capture WSRF Persistent State  ->  your SaveGame  ->  Apply WSRF Persistent State

Saving

  1. Create or use your project’s USaveGame Blueprint.
  2. Add a variable of type WSRF World State Snapshot and mark it SaveGame.
  3. Get the WSRF World State Subsystem.
  4. Call Capture WSRF Persistent State.
  5. Store the returned snapshot in your SaveGame and save it with your existing workflow.

The export contains only Actors whose persistence mode is Persistent or One Shot. An Actor left as Resettable — a normal enemy, a normal prop — is deliberately not written just because a save happened.

Loading

  1. Load your SaveGame with your existing workflow.
  2. Open the destination world.
  3. Call Apply WSRF Persistent State with the stored snapshot.
  4. Inspect the returned report if you need diagnostics.

Loaded Actors are applied immediately. Actors in unloaded World Partition cells, inactive Data Layers, streamed sublevels or unloaded Level Instances are marked for deferred persistent restore and applied when their matching effective identity registers — without forcing unrelated content to load.

The snapshot

FWSRFWorldStateSnapshot is a pure-data struct, schema version 3:

FieldMeaning
SchemaVersionSnapshot schema version
WorldIdentityWhich world the snapshot was captured in
ManifestBuildIdInformational: the manifest build at capture time
CapturedUtcCapture timestamp
ActorsOne FWSRFPersistentActorState per exported record

Each record carries the effective Actor ID, container identity, regions, persistence mode, presence, the captured FWSRFActorState (including Custom State), and a configuration hash.

It holds no AActor, no UWorld and no other UObject instance, which is what makes it safe to serialise into a SaveGame.

Four things are versioned independently:

VersionOwns
FWSRFWorldStateSnapshot::SchemaVersionThe complete snapshot envelope
FWSRFActorState::StateVersionOne Actor’s automatic-state representation
FWSRFActorState::CapturedSectionsWhich sections were intentionally captured — a present-but-empty section and an absent section are different
FWSRFCustomState::VersionThe Actor’s own Custom State contract; it never selects a WSRF storage migration

Common tasks

Keep a shortcut open

Use the Permanent Shortcut preset. If the open state is not already covered by automatic capture — transform, visibility, collision — write it through WSRF Capture Custom State. Save normally; the door is open again in the next session.

Keep a unique pickup consumed or a boss defeated

Use the Unique Pickup or Boss / Elite preset. Their one-time records are excluded unconditionally from every normal reset selection — an empty trigger list is not what protects them. When consumed or destroyed, that presence is exported; if the saved presence is Destroyed or Removed, loading keeps the pickup collected or the boss defeated.

Respawn a normal enemy in a new session

Use the Enemy preset and leave it Resettable. Its temporary dead state is excluded from the export, so a new session starts from the authored state.

The import report

FWSRFPersistenceImportReport:

FieldMeaning
bSuccessThe import ran and the snapshot was compatible
CompatibilityCompatible, TooOld, TooNew, WrongWorld or Invalid
AppliedState restored immediately
DeferredThe matching Actor or container is currently unloaded
SkippedThe record intentionally required no application
MissingNo current or manifest identity matches the saved record
FailedThe record was found but could not be restored safely
VersionMismatchSnapshot or Custom State schema was incompatible
ConfigurationMismatchThe saved configuration differs from the current Actor setup — diagnostic only, the state is still applied with the current settings
DurationMillisecondsWall-clock duration
MessagesPer-record diagnostics

One bad record never prevents the remaining compatible records from being processed.

The export side returns FWSRFPersistenceExportReport: bSuccess, Exported, Skipped, ApproximateMemoryBytes, bSerializedSizeMeasured, ApproximateSerializedBytes, DurationMilliseconds and Errors. ApproximateSerializedBytes is zero unless the capture was explicitly asked to measure serialized size — see Performance.

Versioning and migration

Snapshot schema 3 is the current format. Apply WSRF Persistent State automatically migrates WSRF schema-1 and schema-2 saves to schema 3. WSRF ships and selects both migration steps because the plugin changed the format; a project that saved with either previous format does not need to create or register anything.

  • The built-in v1-to-v2 step preserves every field schema 1 knew how to capture; its new extended-component section is marked absent.
  • The v2-to-v3 step converts Custom State to a compact stream containing the key, value type and active value only, and preserves the project’s Custom State version.
  • During restore, an absent section leaves the destination Actor or component at its construction/Blueprint value. WSRF never interprets absence as an instruction to clear or reset that component.
  • FWSRFPersistentActorState::Presence remains actor-level existence: Loaded, Destroyed and Removed keep exactly their schema-1 meaning after migration.

A schema-3 snapshot is applied directly and never invokes a migrator. A newer snapshot is reported through Compatibility and is not interpreted silently.

The advanced Apply WSRF Persistent State With Migrator node remains strict: passing no migrator to that advanced node rejects an old snapshot as TooOld. Use it only when your project owns an additional legacy format — derive a class from UWSRFSnapshotMigrator, implement MigrateSnapshot, and delegate the WSRF-owned schema steps to UWSRFDefaultSnapshotMigrator if you need them.

The Migrate WSRF Snapshot v1 to v2 helper remains available for compatibility with advanced project migrators, but schema 2 is an intermediate format and must not be submitted alone to a schema-3 runtime.

Project version ≠ WSRF schema

Incrementing the version you pass to the Custom State Writer, and branching on the Reader’s version in WSRF Restore Custom State, is a project-owned contract. That version never triggers a WSRF snapshot migration. WSRF owns migrations caused by WSRF schema changes; your project owns migrations for its own save envelope and its own Custom State versions.

Changed content between game versions

SituationResult
A saved Actor no longer existsReported as Missing; other records still load
A new Actor is absent from an older saveUses its authored configuration
A Level Instance was duplicatedEffective identities keep each placed instance independent
A manifest was rebuilt since the saveHandled per Actor; the save is not invalidated wholesale

Cost and when to call it

Persistence has no Tick, and import uses indexed effective-identity lookup rather than a world scan. Export cost scales with the number of exported records, so capture at an explicit save boundary rather than on a frame-critical path.

Measured round-trips, including real SaveGameToMemory serialisation, are published in Performance.

Advanced diagnostics

FunctionReturns
GetApproximatePersistentSnapshotMemoryBytesEstimated serialized footprint of a snapshot — the name is retained from 1.x for compatibility
GetApproximatePersistentSnapshotSerializedBytesExplicit tagged-serialization measurement
GetLastPersistenceImportReportThe most recent import report
GetLastImportedSnapshotVersionThe schema version of the last import

The World State Inspector shows persistence status, the last import report and the last imported snapshot version alongside the rest of the world state.

Demo

The demo map includes a deliberately tiny demo-only SaveGame class, driven by F5 and F9, to show the whole loop end to end. It is an example of the integration, not a SaveGame system shipped by the plugin.

Last updated: 2026-09-04

Type to search titles, sections and keywords.