Course contentsShow
← Unity Game Development
Lesson 763 of 82811. Performance and Data PersistenceFree lesson

Versioning Game Save Data Structures

Implement a robust versioning strategy to ensure that updated game builds can successfully parse save files created in previous versions.

In this lesson, you will learn how to implement a schema versioning strategy to ensure your game can gracefully handle save files created in older builds as your data structure evolves.

As your game grows, you will inevitably add new features, change variable types, or rename fields in your save objects. If you simply load an old JSON file into a new class structure, your game will likely throw errors or fail to parse critical data. To solve this, you must treat your save file as an evolving contract.

Implementing the Versioning Pattern

The simplest, most robust approach is to include a version integer at the root of your serialized data. When your SaveManager reads the file, it checks this number before passing the data to the rest of your system.

[Serializable]
public class GameSaveData {
    public int schemaVersion = 2; // Incremented whenever the structure changes
    public int playerLevel;
    public string playerName;
}

When loading, use a "migration chain." If the file version is 1, your code performs a series of updates to map it to 2, then potentially 3, and so on. This prevents you from having to write custom logic for every possible combination of older versions.

Migration Strategy

Instead of hardcoding every possible upgrade path, create a SaveMigrator class that holds a sequence of migration methods:

  1. Check: Load the schemaVersion from the JSON header.
  2. Transform: If schemaVersion < CurrentVersion, run the migration logic.
  3. Loop: If version is 1, upgrade to 2, then run the logic for 2 to 3.
  4. Finalize: Save the newly migrated data structure as the current version, so the user doesn't have to re-process the old format next time.

By keeping the version number at the very top of your JSON/Binary structure, your deserialization logic remains lightweight—you only incur the cost of migration when an outdated file is detected, keeping your high-performance game loop uninterrupted during standard saves.

Key Takeaway: Always include a version field in your save files and implement a sequential migration pipeline to transform legacy data into the current structure before it reaches your game’s runtime logic.