In this lesson, you will learn how to unify your ScriptableObject configurations and runtime state into a reliable, layered persistence architecture.
When building games, we often treat "Game Settings" (defined in assets) and "Player Progress" (defined at runtime) as separate entities. A robust persistence layer bridges this gap by acting as a single source of truth that translates volatile runtime data into permanent storage files.
The Layered Approach
To keep your architecture clean, we split data management into three distinct layers:
- Data Models: Simple, serializable classes (using
[System.Serializable]) that hold state. - Storage Providers: Classes responsible for reading/writing these models to disk (e.g., JSON files, binary, or
PlayerPrefs). - Persistence Managers: The "Orchestrator" that bridges your
ScriptableObjectgame actions with the Storage Providers.
By using this approach, your game logic never talks to the hard drive directly. Instead, it talks to a PersistenceManager, which ensures that data is sanitized and serialized correctly before it touches the disk.
Example: Orchestrating the Save
Consider a PlayerData class that tracks level progress. Your PersistenceManager gathers the data from your ScriptableObject event-based systems and triggers the save process:
public class PersistenceManager : MonoBehaviour
{
public PlayerConfig playerConfig; // ScriptableObject settings
public GameState runtimeState; // Runtime tracking
public void SaveGame()
{
var dataToSave = new SaveData(playerConfig, runtimeState);
string json = JsonUtility.ToJson(dataToSave);
File.WriteAllText(Application.persistentDataPath + "/save.json", json);
}
}
This structure prevents corruption because you are serializing a dedicated "container" class rather than dumping live game objects or complex MonoBehaviour references directly. If the runtimeState changes or the playerConfig is updated, the PersistenceManager handles the mapping, keeping your file format decoupled from your project's internal structure.
This is vital for long-term project health: as you evolve your prefabs or add new gameplay features, you can update your SaveData mapping logic without breaking existing save files or forcing a total rewrite of your core systems.
Key Takeaway: Build a middle-ware "Persistence Manager" that maps game-ready data to storage-ready models, ensuring your disk files remain decoupled from your volatile runtime objects.