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

Handling File Corruption and Data Recovery

Learners will build robust validation checks and backup strategies to restore user progress in the event of unexpected file write errors.

In this lesson, you will learn how to design a resilient save system that uses backup strategies to ensure player progress is never lost due to write interruptions or file corruption.

The Problem: Partial Writes

When saving game data to local disk storage, a crash, power loss, or sudden application exit during the file write process can leave your save file in a "corrupted" state. If the file is only partially written, your JSON deserializer will throw an exception the next time the game tries to load, potentially locking the player out of their progress.

The Strategy: Atomic Backups

To prevent this, you should never overwrite your primary save file directly. Instead, implement a "write-to-temp-and-swap" strategy combined with a backup rotation.

  1. Write to a Temporary File: Write your serialized JSON data to a file named save_data.tmp.
  2. Verify Integrity: Before overwriting the main file, verify that the .tmp file is not empty and matches your expected schema.
  3. Atomic Swap: If validation passes, delete the old backup (save_data.bak), rename the current main file (save_data.json) to the backup, and rename your .tmp file to the main file.

This creates a safety net: if the system fails mid-write, the original save_data.json remains untouched, or at worst, you have a save_data.bak from the previous successful session.

Implementation Logic

public void SaveGame(string jsonData) {
    string path = Application.persistentDataPath + "/save.json";
    string backupPath = path + ".bak";
    string tempPath = path + ".tmp";

    // Write to temp file first
    File.WriteAllText(tempPath, jsonData);

    // Validate if file was written successfully
    if (new FileInfo(tempPath).Length > 0) {
        if (File.Exists(path)) {
            if (File.Exists(backupPath)) File.Delete(backupPath);
            File.Move(path, backupPath); // Preserve last known good state
        }
        File.Move(tempPath, path);
    }
}

By keeping a .bak file, your loading logic can perform a "check-and-restore": if save.json fails to load or deserialization returns null, the game can automatically attempt to load the .bak file as a recovery measure.

Key Takeaway: Never overwrite your primary save file directly; use temporary files and backup rotation to ensure you always have a valid fallback if a write operation is interrupted.