Save and load
Choose when loads happen
A manager loads on its own when its asset comes into scope, and again after a slot change. A load that failed is retried every Auto Load Retry Delay seconds, until it lands.
Your own loads run on top of those:
PersistenceManager pm = playerData.PersistenceManager;
pm.Load(); // fire and forget
pm.Load(result => StartGame()); // callback when done
LoadResult syncResult = pm.LoadSync(); // forced synchronous, result inline
LoadResult asyncResult = await pm.LoadAsync(); // async
PersistenceOperation<LoadResult> op = pm.LoadRoutine(); // coroutine: yield return it,
yield return op; // then read op.Result
Persistence.LoadAll(); // every object in scope at once
With Auto Load off, the manager reads nothing until you call Load(), and
refuses every save until it has.
To veto a load, subscribe to the manager's BlockLoad hook.
Choose when saves happen
A manager saves on its own at four moments: when a persistent asset leaves scope, when the game loses focus or pauses, before a slot change, and every Regular Save Delay seconds.
Your own saves run on top of those. Every way of calling Load works for Save
too:
pm.Save(); // fire and forget
SaveResult result = await pm.SaveAsync(); // async
// ...
With Auto Save off, a crash or a task switch loses everything since your last save.
To veto a save from outside a persistent asset, subscribe to the manager's BlockSave
hook:
// Blocks every save, the quit-time one included
manager.BlockSave += source => inCutscene;
// Blocks only the saves your code asked for
manager.BlockSave += source => (source == PersistenceSource.Manual);
React to load and save
To react from outside a persistent asset, subscribe to the manager's
events. OnBeforeLoad and
OnAfterLoad bracket a load, and save and clear have the same pairs.
To react from inside a persistent asset, implement one of two interfaces:
ISerializationCallbacksruns around the serializer, as the serializer-neutralISerializationCallbackReceiver.IScopeCallbacksruns as the asset comes into scope and as it leaves.
Save on quit
A shutdown drain holds the quit open while saves are still in flight, so a game that quits mid-save finishes writing it. The manager's Save Timeout bounds how long that lasts, as do Max Drain Time In Editor and Max Drain Time In Build, in Project Settings > Persistent Asset.
The static Persistence class reports and
controls the drain.
Reset an asset or restore a snapshot
ResetToDefaults() puts the asset back to its authored values in memory, and
Clear() does that and deletes the stored save as well.
SaveData.Snapshot(manager) hands you the asset's
values as a string, and SaveData.Restore(manager, snapshot) puts them back, which covers an
undo step or a checkpoint your game holds itself.
To reset single fields rather than the whole asset, implement
IFieldResettable, whose
DefaultValuesRequested() hands back the authored values as a SaveNode.
Optional hooks
Each of the following is optional, and the package picks it up on its own when your class carries it.
| Hook | Description |
|---|---|
IDirtyTracked | Expose bool IsDirty { get; set; } and set it when you change a field: every save is skipped while it is false, and a save that lands clears it. |
IDynamicInitialize | Runs the first time an asset loads with no save. |
IPersistencePolicy | Fixes Auto Load, Auto Save, Use Slot and Always Global for every asset of the type, over the manager's own settings. |
IUpgradable | Reads a save written by an older build field by field, so a change to your class doesn't strand it. For more information, refer to Version your data. |
IMergeable | Folds another device's save into this one instead of discarding either. For more information, refer to Merge two saves. |
[RequiredSerializer] | Locks the serializer when the data only works with one. |