Checked with version: 2017.3
The data persistence system allows you to save some data during a playthrough, to keep some information on what the Player already did.
Without it, as each zone is a new Scene, entering a zone loads the "default" state of that zone (as it is designed in the editor), but any permanent action the Player took (like grabbing a key or a weapon) would be undone.
Usage in Editor
The data system works through a scripting interface called IDataPersister.
Objects implementing this interface (like the built-in InventoryItem, HubDoor, PlayerInput, etc.) can write and read data from the PersistentDataManager.
MonoBehaviours that implement the interface have a Data Settings foldout that appears at the bottom of their Inspector. The settings comprise of:
Data Tag: This is a unique identifier for the GameObject, used by the manager to link data to that GameObject. It can be anything: some built-in components use an auto-generated Unique ID, but it could also be a manually typed name, like "Zone_3_key" or "Quest_Item_Card".
Persistence Type: There are four types of persistence:
Don't Persist: This allows disabling persistence. This is useful for GameObjects that need to be reset on Scene change (e.g. you may want a door to close again when restarting a level).
Read Only: This GameObject can only read data, not write to it. A way to use this is to have a GameObject with Write Only (see below) with the same Data Tag. This GameObject uses the data that the other GameObject writes for that tag, but is not able to write over it.
Write Only: The GameObject can write data but can't read from it. See Read Only above for example of use.
Read Write: This is the most common case of use. The GameObject reads and writes data with its given Data Tag.
Data Saving/Loading cycle
SaveData is called on all instances of IDataPersister in the scene before a scene transition out.
LoadData is called on all instances of IDataPersister in the scene after a new scene was loaded.
It is possible to manually save data at any time by calling PersistentDataManager.SetDirty(this) on any IDataPersister.
Example of use in code
The way that the data manager can be used in code is by reading its associated data when it's enabled/started and react to it.
For example, the inventory item writes its state to the persistent data (active or not). So when the scene is loaded, the inventory item retrieves the data associated to its tag. If a false value is saved, that means that the GameObject had already been retrieved and it can disable itself.
Another example would be a door saving its state. When the scene is loaded and data is read, it can set itself to the desired state (e.g. open/closed).