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

Managing Version Compatibility in Save Systems

Implement data migration strategies to ensure that older save files remain compatible when you update your game's data structure in future versions.

In this lesson, you will learn how to implement "Data Migration" strategies to ensure your players' save files remain functional as your game's data schema evolves.

When you add new features or refactor your save system, your old JSON or binary files often become "obsolete." If your current code expects a PlayerLevel field but the old file only contains PlayerScore, the deserializer will throw an error or default the value to zero, potentially breaking the player's experience.

The Versioning Strategy

The most robust approach is to include a SaveVersion integer at the root of your serialized data. Every time you change your data structure, you increment this version number. When loading, you read the version first and pass the raw data through a chain of "migration" functions.

[Serializable]
public class SaveData {
    public int version; // Incremented on every schema change
    public int playerLevel;
    public int playerScore;
}

public void LoadGame(string json) {
    SaveData data = JsonUtility.FromJson<SaveData>(json);
    
    // Migrate old versions to current
    if (data.version < 2) {
        data.playerLevel = 1; // Default for legacy saves
        data.version = 2;     // Update to new version
    }
    
    ApplyData(data);
}

Why Migration Matters

By using a migration chain, you avoid writing "dirty" code that tries to guess whether a field exists. Instead, you create a clear path: Version 1 -> Version 2 -> Version 3. Each step only handles the specific changes made in that update.

For performance-heavy games, ensure your migration logic is lightweight. You don't want to re-serialize the entire file structure unnecessarily. If your file is binary-based, consider using an Intermediate Data Transfer Object (DTO) to map old fields to new structures, ensuring that your core game logic always receives an object shaped exactly how the current build expects.

By treating save files as "living documents" that require transformation, you eliminate the frustration of players losing their hard-earned progress during routine game updates.

Key Takeaway: Always store a version index in your save files and implement a migration chain to transform legacy data structures into your current format before the game logic consumes them.