Reference for every public type and member in the Core area. Red text flags the exceptions a member can throw. See the API overview for the other areas.

CoreThe foundation: persistent objects, managers and the save API.

PersistentScriptableObject

SOabstract

Base class for your data. Inherit it and its serialized fields persist between sessions.

Properties
PersistenceManager PersistenceManager { get; }The manager in charge of this object's persistent data.

PersistenceManager

PMabstractextending

Saves and loads a persistent object. The built-in managers derive from it; so does any custom one.

State & identity
bool IsReady { get; }Whether the target holds its data and is safe to read and save. The one rule.
Awaitable WhenReady { get; }Await (or yield) until everything that decides readiness has settled (the automatic load and its imports, a queued load or Slots.LoadFrom, an in-flight or queued clear, and any follow-up issued while waiting), then read IsReady.
Object Target { get; }The persistent object this manager saves and loads.
string UniqueID { get; }Identifier unique to this manager.
Serializer Serializer { get; protected set; }The serialization system in use.
string Slot { get; set; }Current slot (multi-slot targets). Setting it switches slot as a scope transition. The setter throws InvalidOperationException in the editor only when set outside play mode.
bool UseSlot { get; }Whether the target is IMultiSlot.
string GetStorageLocation() / GetStorageLocation(string slot)Where this manager stores its data (the current slot, or a given one), or null (a normal answer for remote managers).
Load / Save / Clear operations
Every method below throws InvalidOperationException in the editor only when called outside play mode (never at runtime).
LoadResult LoadSync()Force synchronous; the result is final on return.
void Load()Fire and forget; wireable to a UnityEvent.
void Load(Action<LoadResult> onComplete)Default; sync when it can, else async, then callback.
Task<LoadResult> LoadAsync(ExecutionMode? executionModeOverride = null)Async; await the result.
PersistenceOperation<LoadResult> LoadRoutine()Coroutine; yield return it, then read Result.
SaveResult SaveSync()Force synchronous save.
void Save()Fire and forget save (wireable to a UnityEvent).
void Save(Action<SaveResult> onComplete)Default save, then callback.
Task<SaveResult> SaveAsync(ExecutionMode? executionModeOverride = null)Async save; await the result.
PersistenceOperation<SaveResult> SaveRoutine()Coroutine save.
ClearResult ClearSync()Force synchronous clear: deletes the slot's save, resets the target to defaults, pauses saving until the next load.
void Clear()Fire and forget clear (wireable to a UnityEvent).
void Clear(Action<ClearResult> onComplete)Default clear, then callback.
Task<ClearResult> ClearAsync(ExecutionMode? executionModeOverride = null)Async clear; await the result.
PersistenceOperation<ClearResult> ClearRoutine()Coroutine clear.
Other operations
All three throw InvalidOperationException in the editor only when called outside play mode (never at runtime).
void ResetToDefaults()Reset the target's fields to pre-play values, in memory only (the save is untouched).
string Snapshot()Capture the target's current values into a string for a checkpoint. Returns null when there is no serializer or the encode fails.
bool Restore(string snapshot)Restore from a Snapshot string, in memory only. Returns false when the string is null, could not be decoded, or persistence is disabled.
Events
OnBeforeLoad / OnAfterLoadAround each load that runs (with source, and result on After).
OnBeforeSave / OnAfterSaveAround each save that runs.
OnBeforeClear / OnAfterClearAround each clear that runs.
BlockLoad / BlockSave / BlockClearReturn true from a subscriber to veto the operation.
Settings (configurable in the inspector / overridable in a subclass)
bool AutoLoad / AutoSaveWhether to load on launch and save at safe points automatically.
float RegularSaveDelay / AutoLoadRetryDelayTimer cadences (use NoRegularSave / NoAutoLoadRetry to disable).
const float MinimumRegularSaveDelay / MinimumAutoLoadRetryDelay = 5 · NoRegularSave / NoAutoLoadRetry = 0A positive delay is clamped up to the minimum; the No* value (or lower) disables the timer.
ExecutionMode ReadExecutionMode / WriteExecutionModeWhich sync/async paths the manager supports, and the default.
float LoadTimeout / SaveTimeout / ClearTimeoutSeconds an async operation may run before cancellation.
For implementers (protected)
LoadResult ReadPayloadSync(PersistenceSource source, string slot)Read and return the stored payload (or Invalid / Failure).
SaveResult WritePayloadSync(PersistenceSource source, string slot, string payload)Persist the payload.
ClearResult ClearPayloadSync(PersistenceSource source, string slot)Delete the stored data. Manual for a clear or slot delete the game requested, Automatic for the system wiping a consumed import source.
LoadResult ReadFallbackPayloadSync(PersistenceSource source, string slot)The payload the read returned would not decode: return an alternate copy of the save if your storage keeps one (the default returns Invalid, meaning none).
ReadPayloadAsync / WritePayloadAsync / ClearPayloadAsync / ReadFallbackPayloadAsyncAsync equivalents (with a CancellationToken).
string StorageLocation(string slot)Report a stable storage path or key.
void OnEnteringScope() / OnLeavingScope()Per-session setup and teardown.
void OnImportingFrom(PersistenceManager source, string slot)An empty load is recovering by importing this source's save: it was just decoded into the target and is about to be re-persisted here. Override to carry storage facts your manager keeps about a save across the import.
PersistencePolicy Constraint / bool SelfBoundsAsyncOperationsFix auto-load/save the manager cannot work without; declare it bounds its own async timeouts.
void Log(string text, LogLevel level = None)Write to the manager's inspector log (development only).

Persistence

static

Global entry point for state and operations shared across every manager.

State & events
Awaitable WhenAllReady { get; }Await (or yield) until every active manager's load has settled.
IReadOnlyList<PersistenceManager> ActiveManagers { get; }Live view of every active manager.
int ManagerCount { get; }Count of currently active managers.
bool IsDraining { get; }Whether a shutdown save drain is running.
void ForceQuitDrain()Cut a running shutdown drain short (unsaved data may be lost).
event Action<PersistenceManager> ManagerAdded / ManagerRemovedA manager went in or out of scope.
event Action OnShutdownDrainStarted / OnShutdownDrainCompletedAround the shutdown save drain (play-mode exit or app quit).
OnBeforeAnyLoad / OnAfterAnyLoadAround any manager's load: (manager, source), and (manager, source, LoadResult) on after.
OnBeforeAnySave / OnAfterAnySaveAround any manager's save (with SaveResult on after).
OnBeforeAnyClear / OnAfterAnyClearAround any manager's clear (with ClearResult on after).
Operations on every active manager
Every method below throws InvalidOperationException in the editor only when called outside play mode. ClearAll* permanently deletes player data.
LoadResult[] LoadAllSync()Force synchronous; every result is final on return.
void LoadAll()Fire and forget (wireable to a UnityEvent).
void LoadAll(Action<LoadResult[]> onComplete)Default; callback with every result.
Task<LoadResult[]> LoadAllAsync(ExecutionMode? executionModeOverride = null)Async; await every result.
PersistenceOperation<LoadResult[]> LoadAllRoutine()Coroutine; yield then read Result.
SaveResult[] SaveAllSync() / void SaveAll() / SaveAll(Action<SaveResult[]>)Save every manager: sync, fire-and-forget, callback.
Task<SaveResult[]> SaveAllAsync(ExecutionMode? = null) / PersistenceOperation<SaveResult[]> SaveAllRoutine()Save every manager: async, coroutine.
ClearResult[] ClearAllSync() / void ClearAll() / ClearAll(Action<ClearResult[]>)Clear every manager: sync, fire-and-forget, callback.
Task<ClearResult[]> ClearAllAsync(ExecutionMode? = null) / PersistenceOperation<ClearResult[]> ClearAllRoutine()Clear every manager: async, coroutine.

Slots

static

Operate on a slot's saved data (copy, rename, delete, snapshot to, load from).

Members
string GlobalSlot { get; set; }Slot shared by every manager; setting it switches all of them.
ClearResult[] DeleteSync(string slot, params IMultiSlot[] targets) / void Delete(...) / Delete(string slot, Action<ClearResult[]> onComplete, ...)Delete a slot's storage for each target: sync, fire-and-forget, callback. Permanently deletes data, no undo.
Task<ClearResult[]> DeleteAsync(...) / PersistenceOperation<ClearResult[]> DeleteRoutine(...)Delete a slot's storage: async, coroutine.
SaveResult[] CopySync(string fromSlot, string toSlot, params IMultiSlot[] targets) / void Copy(...) / Copy(string fromSlot, string toSlot, Action<SaveResult[]> onComplete, ...)Copy a slot's storage onto another: sync, fire-and-forget, callback. Overwrites the destination.
Task<SaveResult[]> CopyAsync(...) / PersistenceOperation<SaveResult[]> CopyRoutine(...)Copy a slot's storage: async, coroutine.
SaveResult[] RenameSync(string fromSlot, string toSlot, params IMultiSlot[] targets) / void Rename(...) / Rename(string fromSlot, string toSlot, Action<SaveResult[]> onComplete, ...)Rename a slot (copy then delete): sync, fire-and-forget, callback. Moves data, no undo.
Task<SaveResult[]> RenameAsync(...) / PersistenceOperation<SaveResult[]> RenameRoutine(...)Rename a slot's storage: async, coroutine.
SaveResult[] SaveToSync(string slot, params IMultiSlot[] targets) / void SaveTo(...) / SaveTo(string slot, Action<SaveResult[]> onComplete, ...)A real save aimed at another slot: snapshot each target's live data onto that slot's storage (the current slot's save is untouched): sync, fire-and-forget, callback. Raises the save events; overwrites the destination; refused on the current slot, a not-ready target, or when saving is blocked.
Task<SaveResult[]> SaveToAsync(...) / PersistenceOperation<SaveResult[]> SaveToRoutine(...)Snapshot to a slot: async, coroutine.
LoadResult[] LoadFromSync(string slot, params IMultiSlot[] targets) / void LoadFrom(...) / LoadFrom(string slot, Action<LoadResult[]> onComplete, ...)A real load aimed at another slot: bring its saved data into the ongoing game (load events, save upgrades and readiness included); the next save persists it onto the current slot, and the source slot is never modified. Refused on the current slot or with no slot set; does nothing when the source holds no usable save.
Task<LoadResult[]> LoadFromAsync(...) / PersistenceOperation<LoadResult[]> LoadFromRoutine(...)Load from a slot: async, coroutine. Delete / Copy / Rename / SaveTo / LoadFrom (all shapes) throw InvalidOperationException in the editor only when called outside play mode.
OnSlotUpdated / OnSlotDeleted / OnSlotCopiedRaised as slot storage changes (a SaveTo snapshot raises OnSlotUpdated with the written slot).

GlobalPersistedData

static

Reach a registered persistent object from anywhere, by type, with no serialized reference. An IAlwaysGlobal target registers itself; you can also register your own.

T Find<T>(Func<T, bool> filter = null) where T : classThe first registered target assignable to T (a concrete type or interface) matching the optional filter, or null.
IEnumerable<T> FindAll<T>(Func<T, bool> filter = null) where T : classEvery registered target assignable to T matching the filter, as a fresh snapshot.
void Add(ScriptableObject target) / AddPermanent(ScriptableObject target)Register a target manually (AddPermanent cannot be undone by Remove).
bool Remove(ScriptableObject target)Unregister a target added with Add; returns whether it was removed.

Settings

static

Static access to the package settings (Project Settings > Persistent Asset).

Members
bool LoadedWhether the configured settings are available. Always true in the editor; in a player it turns true when the settings shipped with the build finish loading, before the first scene, so only code running earlier (typically the automatic load of a preloaded persistent asset) can observe false. While false, Get answers defaults: an operation whose outcome must match the configured values (deriving a key from the security secret) should fail retryably instead of proceeding on them.
T Get<T>() where T : SettingsEntry, new()The project's instance of a settings section (or a default). Treat the result as read-only: runtime changes to it are not persisted.
void Save()Persist settings changed from code (editor only; safe to call anywhere).

SettingsEntry

abstractextending

Base class for a settings section. Subclass and decorate with [InspectorDisplay].

Result

abstract

Base for operation outcomes. Use the intent-named flags rather than the raw Type.

Members
ResultType Type { get; }The outcome category.
bool IsSuccess / IsFailure / IsIgnored / IsCancelled / IsBusyIntent-named checks on the outcome.
string Message { get; }Optional explanation (often set on Ignored / Failure).
Exception Exception { get; }Set when Type is Exception.
double ElapsedMilliseconds { get; }Operation duration (NaN in non-development builds).
string ToString() / void Deconstruct(out ResultType, out string, out Exception[, out double])Readable summary; deconstruct into its fields (with or without the elapsed time).

LoadResult

sealed

A load outcome. Adds IsInvalid (no usable data, the normal first run). Factory methods Success(string payload, string message = null), Invalid(string message = null), Failure(string message = null) for managers.

SaveResult

sealed

A save outcome. Factory methods Success(string message = null), Failure(string message = null).

ClearResult

sealed

A clear outcome. Factory methods Success(string message = null), Failure(string message = null).

ResultType

enum
SuccessThe operation succeeded.
FailureFailed; for a load, temporarily unavailable, a retry might help.
ExceptionCode threw.
CancelledStarted but abandoned (timeout, superseded, left scope).
InvalidLoad only: no usable data (missing or corrupt). The normal first run.
IgnoredNever ran (not dirty, blocked, no slot, not loaded yet, shutting down, superseded while queued, busy).

ExecutionMode

enum
PreferSync / PreferAsyncSupports both; defaults to the named one.
SyncOnly / AsyncOnlyOnly that path; as an override, fails when unsupported.

PersistenceSource

enum
ManualA load/save/clear method was called.
AutomaticTriggered by the system (launch, safe point, timer, import-source read or wipe).
SlotCopyA Slots copy or rename is reading or writing a slot's storage, moving the payload verbatim.
SlotSnapshotA Slots.SaveTo is writing the target's live data to a slot other than the current one: like a manual save, aimed elsewhere. Only seen by the read/write methods of a custom manager; the events only ever carry Manual or Automatic.

PersistenceOperation<T>

sealed

Coroutine handle on a running operation (where T : class; T is a Result or Result[]). yield return it; Result (null while running), IsDone.

IMultiSlot

iface

Marker: save and load under multiple named slots. No members.

IUpgradable

iface

Migrate old saves forward. int SaveVersion, void Upgrade(int fromVersion, SaveNode oldData), bool Downgrade(int fromVersion).

IFieldResettable

iface

Reset or restore individual fields. Events DefaultValuesRequested and CurrentValuesRequested return a SaveNode (do not subscribe from your own code).

IScopeCallbacks

iface

OnBeforeScopeIn(string slot, bool enable), OnAfterScopeOut(string slot, bool disable). The flags mark the first scope-in and final scope-out of the session.

ISerializationCallbacks

iface

Serializer-neutral OnBeforeSerialize() / OnAfterDeserialize().

IDirtyTracked

iface

Skip saves while unchanged. bool IsDirty { get; set; } (reset to false after a successful save).

IDynamicInitialize

iface

void DynamicInitialize() runs once after a load found no save (never overwrites a save, never in edit mode).

IPersistencePolicy

iface

PersistencePolicy Policy { get; }. The PersistencePolicy struct's non-null AutoLoad / AutoSave override the manager.

IAlwaysGlobal

iface

Marker: keep the object loaded all session and reachable via GlobalPersistedData. No members.

PersistencePolicy

struct

The manager settings an IPersistencePolicy object can drive; a null field leaves the manager's own setting in charge.

bool? AutoLoad { get; set; } / bool? AutoSave { get; set; }Non-null values override the manager's AutoLoad / AutoSave.
static readonly PersistencePolicy DefaultDrives nothing (every field null).

Serializer

abstractextending

Custom serialization. Must not fail on valid data.

string SerializeToString(Object obj, string backReferenceFieldName)Object to string.
bool DeserializeFromString(string str, Object obj)String into object; returns success.
SaveNode ParseToNode(string str)Parse to a neutral tree for upgrades (null if unsupported).
bool SupportsNode { get; }Whether ParseToNode returns a usable tree.

SaveNode

abstract

Read-only, format-neutral view of a saved payload, handed to IUpgradable.Upgrade.

this[string key] / this[int index]Object member / array element (or Missing).
bool Exists { get; } / int Count { get; }Presence and array length.
AsInt / AsFloat / AsBool / AsString / AsEnum<T> ...Typed readers with a fallback.
AsVector2/3/4 / AsVector2Int/3Int / AsColor / AsColor32 / AsQuaternion ...Common Unity-type readers.
Missing (static) · SaveNode Object(Dictionary<string, SaveNode> members) / Array(List<SaveNode> elements) / Value(string text)Build nodes (for a custom serializer).
IEnumerator<SaveNode> GetEnumerator()SaveNode is IEnumerable<SaveNode>: foreach over an array node's elements.

Attributes

attr
[PersistentScriptableObject(string persistenceManagerFieldName)]
string PersistenceManagerFieldName { get; }
Make a ScriptableObject persistent without inheriting the base class, naming its serialized PersistenceManager field.
[InspectorDisplay(string name, string description = null)]
string Name / Description { get; }, int Order { get; set; }, string Category { get; set; }
Display name, description, ordering and submenu for a manager, serializer or tooling method in the inspector / its menu. The constructor throws ArgumentException when name is null or whitespace.
[Breaking(string warning = null)]
string Warning { get; }
Mark a manager field whose change would orphan existing saves, so the inspector warns and locks it.
[PersistenceManagerInfo]
StorageKind StorageKind { get; set; }
Declare type-level facts of a manager class (inherited by subclasses). StorageKind: Durable (real player saves, the default without the attribute), Transient (nothing recoverable: never lockable, no import copy kept of it), or Test (a fake manager: assigning it always keeps an import copy of the replaced setup, restorable in one click, and it never ships: a non-development build fails while one exists, a development build warns).
[RequiredSerializer(Type serializerType)]
Type SerializerType { get; }
Lock a persistent object to a specific serializer (redeclarable on a subclass).

LogLevel

enum
None / Info / Warning / ErrorSeverity of a persistence log message, used with the manager's Log().

InGameLogsViewer

MB

Add this component to a GameObject for an on-screen view of every active manager's logs (editor and development builds only; in a release build it self-destroys on Awake).

PersistentAssetConsole

staticextending

Write to the Unity console with the standard colored "[Persistent Asset ...]" prefix. Pass the sub-module name as module (e.g. nameof(BuiltIns)), or null for Core.

void Log(string module, string message, Object context = null)Informational message.
void LogWarning(string module, string message, Object context = null) / LogError(...)Warning / error message.
void LogException(Exception exception, Object context = null)Log an exception (native entry, no prefix).