How saving works
The persistent asset
A persistent asset is any asset the package saves:
- A data class of your own.
- The Prefs asset.
- A Persistent Variables asset.
- A Scene State.
Each one carries a Persistence Manager, which decides where its data is stored.
Scope and global assets
A persistent asset is in scope while it is loaded, which lasts from the first reference to it until Unity unloads it. An asset that nothing references never loads and never saves.
Turn on Always Global and the asset stays in scope at all times and registers itself, which makes it reachable by type from anywhere:
GameSettings settings = GlobalPersistedData.Find<GameSettings>();
GlobalPersistedData.Add registers an asset dynamically, until Remove takes it
back out.
Load, save and clear
A manager loads when its asset enters scope, and retries when that load fails. It then saves at the safe points: on unload, on focus loss or pause, and on a timer. You can tune or turn off each of those. For more information, refer to Choose when loads happen and Choose when saves happen.
Clear deletes the stored save, resets the asset to its authored values, and pauses saving until the next load.
Run an operation from code
Load, save and clear each come in five calling styles:
PersistenceManager pm = playerData.PersistenceManager;
pm.Save(); // fire and forget
pm.Save(result => ShowSavedTick()); // callback when done
SaveResult syncResult = pm.SaveSync(); // forced synchronous, result inline
SaveResult asyncResult = await pm.SaveAsync(); // async
PersistenceOperation<SaveResult> op = pm.SaveRoutine(); // coroutine: yield return it,
yield return op; // then read op.Result
When the data is ready
IsReady states whether the asset holds real data. It is false before the first load
lands, while a slot change reloads, after a clear until the next load, and after a load that failed. The
package refuses every save while it is false, so a save can't overwrite data a retry might still
recover.
Reading the asset before then is safe, but it holds its authored values rather than the player's.
To delay something until the data is ready to use:
await playerData.PersistenceManager.WhenReady;
if (playerData.PersistenceManager.IsReady)
StartGame(playerData);
OnReadinessChanged is the event form, if you want to react rather than wait.
How much of this your game has to handle depends on the manager it saves through:
| Manager | What your game does about readiness |
|---|---|
| Player Prefs, Session (Memory) | Nothing. The load is instant and can't fail, so the asset is never not ready. |
| Prototype, Local File | Usually nothing, because the load finishes before your first Awake. It fails only in rare cases, on a locked file or a runtime secret nobody supplied, and handling those is your call. |
| The remote managers | Gate on it. The load waits on sign-in and connectivity, so a player meets the not-ready state in an ordinary session. |
When the gate doesn't pass, Readiness.Reason says why:
Readiness readiness = playerData.PersistenceManager.Readiness;
if (readiness) // reads as its IsReady
ShowContinue();
else switch (readiness.Reason)
{
case NotReadyReason.Loading: ShowSpinner(); break;
case NotReadyReason.LoadFailed: ShowRetry(); break;
case NotReadyReason.NoSlot: ShowSlotPicker(); break;
}
IsReady is the only signal that says whether the data
is safe. Use Reason and Origin to decide what the player sees, never to decide
whether to read or write the data.Edit mode and Play mode
Unity normally writes the changes a play session makes into a project asset, so it comes out of Play mode holding whatever the game left in it. Persistent Asset undoes that. Enter Play mode, change values, leave Play mode, and the asset shows the values you authored again, while the save it wrote keeps them.
Act on every manager at once
The static Persistence class mirrors every
operation and every event across every manager in scope, so one call saves, loads or clears the lot.
Choose a persistence manager
Each asset picks one manager from the dropdown at the top of its Inspector window, and switching manager changes nothing in your game code. The following table lists the managers the package ships.
| Manager | Saves to | Use it for |
|---|---|---|
| None | Nowhere | Turning saving off |
| Prototype | A file on the device, placed for you | Getting started, jams, prototypes |
| Local | ||
| Local File | Files you name and place | Shipping your game |
| Player Prefs | Unity's PlayerPrefs | Small saves a silent loss would not hurt |
| Remote | ||
| Server (HTTP) | A backend service, or a server of your own | Saves that follow the player between devices |
| Cloud Save (UGS) | Unity Gaming Services | The same, with no server of your own |
| Steam Cloud | Steam | Steam releases |
| Other | ||
| Platform (Routing) | A different manager per platform | One project shipping to several platforms |
| Session (Memory) | Memory, gone when the game closes | Values kept for one play session only |
| Test | Nothing, it fakes the result you ask for | Checking how your game handles a save that fails |
Two cases need a manager of your own. A console saves through its platform SDK, so it needs a small manager you write, and any storage this table doesn't reach needs a custom manager.