Persistent Data Manager

The PersistentDataManager class provides static methods to:

  • Record and apply persistent data to the Lua environment
  • Get and apply savegame data

See the PixelCrushers.DialogueSystem.PersistentDataManager reference page for details about the methods.


Overview

Briefly, to save game data call PersistentDataManager.GetSaveData(). The example below saves the game to a PlayerPrefs entry under the key "MySavedGame".

PlayerPrefs.SetString("MySavedGame", PersistentDataManager.GetSaveData());

To load saved game data, call PersistentDataManager.ApplySaveData(). The example below loads a game from the same "MySavedGame" PlayerPrefs entry.

PersistentDataManager.ApplySaveData(PlayerPrefs.GetString("MySavedGame"), DatabaseResetOptions.KeepAllLoaded);

You can call Record() and Apply() manually during level changes. For example, you might want to keep track of an NPC's location between levels. Normally, when you reload a level, the NPC will be reset to its initial location in the scene file. To track its location, add a PersistentPositionData component to the NPC. Before leaving the level, call PersistentDataManager.Record() to allow the NPC to record its position in the Lua environment. When returning to the level, call PersistentDataManager.Apply() to allow the NPC to retrieve its position from the Lua environment.

By default, recording and saving are blocking operations. This means they pause Unity while they run. If your dialogue database is very large and you're including SimStatus data, you may want to use the asynchronous versions to allow Unity to run while the game is saving. See: Asynchronous Saving and Recording.


General Configurable Properties

You can configure these properties, as well as the properties for Asynchronous Saving and Recording, on the Dialogue Manager's inspector or by assigning their values in a script.

includeActorData property

By default, the PersistentDataManager class records the contents of the Actor[] table. If you want to exclude this from save-game data, set includeActorData to false.


includeAllItemData property

By default, the PersistentDataManager class records only the Item[].State and Item[].Track fields (used by quests) to keep the saved-game data size small. If you have changed other fields at runtime and want to record their values, set includeAllItemData to true.


includeLocationData property

By default, the PersistentDataManager class does not record the Location[] table. To record it, set includeLocationData to true.


includeSimStatus property

By default, to keep saved game sizes small, the PersistentDataManager class doesn't record the currently-loaded conversations' SimStatus values into the saved-game data. If you use SimStatus in your dialogue entry conditions, you may want to set the includeSimStatus property to true.


saveConversationSimStatusWithField property

When saving SimStatus, by default it saves each conversation's SimStatus data under the conversation's ID number. If you want to save it under a different field, set saveConversationSimStatusWithField to a non-blank value. For example, to save SimStatus under the conversation's Title, set the value to "Title". Keeping this blank (and using the conversation's ID) produces smaller saved games.


saveDialogueEntrySimStatusWithField property

When saving SimStatus, by default it saves each dialogue entry's SimStatus data under the dialogue entry's ID number. If you want to save it under a different field, set saveDialogueEntrySimStatusWithField to a non-blank value. For example, to save SimStatus under the entry's Title, set the value to "Title". Keeping this blank (and using the entry's ID) produces smaller saved games.


includeStatusAndRelationshipData property

By default, the PersistentDataManager class records the status and relationship tables used by the status and relationship Chat Mapper Functions. If you don't use these functions, you can reduce the size of saved-game data slightly by setting includeStatusAndRelationshipData to false.


recordPersistentDataOn property

By default, the PersistentDataManager class tells all scripts on all GameObjects in the scene to record and/or apply their persistent data if supported. This makes it very easy to add persistent data capability by simply adding OnRecordPersistentData() and OnApplyPersistentData() methods to any MonoBehaviour script.

However, if your scene has a very large number of GameObjects, this can take some time. You can configure more precise notifications by changing recordPersistentDataOn to RecordPersistentDataOn.OnlyRegisteredGameObjects. However, your persistent data components must then also call PersistentDataManager.RegisterPersistentData(GameObject) to receive notifications and PersistentDataManager.UnregisterPersistentData(GameObject) before being destroyed to stop receiving notifications.


Use LevelWillBeUnloaded Before Loading Levels

Call PersistentDataManager.LevelWillBeUnloaded() before loading a new level.

Some persistent data components, such as Persistent Destructible, record data in the Lua environment when a game object is destroyed during play. Game objects are also be destroyed when you load a new level. In this case, you don't want to record it in the Lua environment. The LevelWillBeUnloaded() method tells these components to ignore the OnDestroy() message.

The LevelManager and GameSaver components will automatically call LevelWillBeUnloaded() for you.


Asynchronous Saving and Recording

If your dialogue database is very large and you're including SimStatus data, you can use PersistentDataManager.RecordAsync() and PersistentDataManager.GetSaveDataAsync() to allow Unity to run while GameObjects are recording their save data and the game is saving.

To record persistent data asychronously, call RecordAsync:

PersistentDataManager.RecordAsync();

To get save data asynchronously, call GetSaveDataAsync. This returns an AsyncSaveOperation object. Use it similarly to this:

var asyncOp = PersistentDataManager.GetSaveDataAsync();
while (!asyncOp.isDone) {
yield return null;
}
string mySaveData = asyncOp.content;

Two static integer variables define how much work is done each frame. You can adjust their values at runtime.

Variable Description
asyncGameObjectBatchSize How many scene GameObjects are sent "OnRecordPersistentData" each frame (default: 1000)
asyncDialogueEntryBatchSize How many dialogue entries' SimStatus values are recorded each frame; only used if saving SimStatus (default: 100)

<< Save System | How to Integrate with Gameplay >>