Answer the questions that come up while building on the package, from when each hook runs to what happens to an old save in a new build, with annotated diagrams.
Each hook runs at a fixed point in the asset's session, from the moment Unity loads the asset until it unloads
it. Use this order to decide where your setup and cleanup code goes.
Read or change the data only once IsReady is true, at step 6. OnEnteringScope() at
step 5 does not wait for the load, so with an asynchronous manager the data is usually not there yet.
A load, save or clear that returns Ignored did nothing on purpose. Find the reason here before
looking for a bug.
In the Editor, the manager's log in the Inspector names the reason for every ignored call. To get past an
IsBusy result:
From a synchronous call, call Save, Load or Clear instead: they
queue behind the running operation.
From an event handler, or from OnBeforeScopeIn or OnReadinessChanged during a
slot change, start the call after the handler returns. The asynchronous forms are refused there too.
A LoadSync that has to read an import copy only readable asynchronously also answers
IsBusy, and the load goes on in the background: await WhenReady.
Overlapping operations
You can call Load, Save and Clear at any time, even while another
operation on the same asset is still running. Nothing overlaps, and your calls take effect in the order you make
them: each one is answered as this table shows.
Every load ends in one of three results, and the result tells you what the asset now holds.
An unreadable save is treated as no save because it never becomes readable again, so blocking saves would
strand the player for good. A failed read may succeed on a retry, so the asset is not made ready over a save it could not reach.
For what to show the player in each case, refer to When a save doesn't
load.
Slot change
Changing the slot saves the slot you leave and loads the one you enter, in one call.
The reset at step 7 happens even with AutoLoad off, so the old slot's values never show while
the new one loads. For setting up slots, refer to Set up save
slots.
Quitting mid-save
A player who quits while a save is running does not lose it: the game waits for the save to finish, up to
the limits you set.
Use the two events to show a "saving..." message. A game killed by the operating system gets no wait, so only
saves that already finished are kept. For the settings, refer to Save
on quit.
Versioning and migration
Two tools keep a player's save working across your releases. IUpgradable handles a change to the
data, such as a renamed or merged field. An import copy handles a change to where or how the save is stored,
such as a new file name or a new serializer.
What the version check decides
Raise SaveVersion whenever a release changes the data in a way the serializer cannot follow on
its own.
An import copy moves each player's save to the new setup once, the first time the new setup finds nothing.
A storage change and a data change can ship in the same release. For the Editor side, refer to Lock and
migrate saves.
Module dependencies
Use this map to see what a module needs before you delete it, and which package turns an optional one on.
An assembly is named PersistentAsset.<Module>.<SubModule>, such as
PersistentAsset.BuiltIns.Essentials, plus the suffix of its kind. Test assemblies never reach a
player build.
Steam also builds only for the Editor, Windows, macOS, Linux and Android. For installing the optional
modules, refer to
Optional modules.