Archived on 2026-10-24. This is a historical implementation note, not current setup instructions or an active task list. Original claims, code examples, file paths, and completion statements have not all been revalidated. Use the current documentation and issue register for maintenance decisions.
SaveDataDebugger - Comprehensive Save Data Debugging System¶
Overview¶
The SaveDataDebugger is a utility class designed to help diagnose issues with player data creation, loading, and migration in the save system. It provides detailed validation and logging for PlayerData objects at every stage of the save data pipeline.
Purpose¶
- Identify where PlayerData dictionaries become null
- Validate JSON serialization/deserialization
- Check encryption/decryption integrity
- Diagnose legacy save migration issues
- Track data flow through the save system
Features¶
1. PlayerData Validation¶
Method: DebugPlayerData(PlayerData playerData, SaveDataType dataType, string context)
Validates all aspects of a PlayerData object:
- Checks if PlayerData is null
- Validates basic fields (version, soulPoint, chaosFragment)
- Validates all 6 dictionaries:
- unlockedChar
- unlockedAchievement
- unlockedSpecialUpgrade
- shopUpgrade
- unlockedStage
- totalDataCounter
- Checks boolean flags (legacyMigrated, isFirstLaunch)
- Reports null dictionaries with clear error messages
- Shows sample entries from each dictionary
2. JSON Serialization Testing¶
Method: DebugJsonSerialization(PlayerData playerData)
Tests Unity's JsonUtility serialization/deserialization: - Serializes PlayerData to JSON - Checks JSON length - Deserializes back to PlayerData - Critical Check: Verifies if dictionaries survive the round-trip - Reports if dictionaries become null (common Unity JsonUtility issue)
3. Encryption/Decryption Testing¶
Method: DebugEncryption(string data)
Validates encryption/decryption pipeline: - Encrypts test data - Decrypts back - Compares original vs decrypted - Reports any mismatches
4. Legacy Data Validation¶
Method: DebugLegacyData(List<PlayerData> legacyData)
Validates legacy save files before migration: - Checks if legacy data list is null - Counts legacy saves - Validates each legacy PlayerData - Reports null legacy saves - Shows achievement data from each legacy save
5. Merged Data Validation¶
Method: DebugMergedData(PlayerData merged, List<PlayerData> sources)
Validates data after merging: - Shows number of sources - Reports final currency values - Validates merged achievement dictionary - Reports if merged data is null
6. Full Diagnostic¶
Method: RunFullDiagnostic(PlayerData playerData, SaveDataType dataType, string context)
Runs comprehensive diagnostic including: - Complete PlayerData validation - JSON serialization test - Formatted output with clear headers
7. File Operations¶
Method: DebugFileOperations(string filePath, string operation)
Logs file operation details: - Operation type (load, save, etc.) - File path - File existence check
Integration Points¶
The debugger is integrated into SaveManager at these key points:
1. CreateNewPlayerData()¶
SaveDataDebugger.RunFullDiagnostic(Player, SaveDataDebugger.SaveDataType.NewSave, "CreateNewPlayerData");
2. LoadNewEncryptedSave()¶
SaveDataDebugger.DebugFileOperations(PLAYER_FILE, "LoadNewEncryptedSave");
Player = JsonUtility.FromJson<PlayerData>(json);
SaveDataDebugger.RunFullDiagnostic(Player, SaveDataDebugger.SaveDataType.LoadedSave, "LoadNewEncryptedSave");
3. MigrateLegacySaveAsync()¶
SaveDataDebugger.DebugLegacyData(legacyData); // Before merge
Player = MergeLegacyPlayers(legacyData);
SaveDataDebugger.DebugMergedData(Player, legacyData); // After merge
SaveDataDebugger.RunFullDiagnostic(Player, SaveDataDebugger.SaveDataType.MigratedSave, "MigrateLegacySaveAsync");
Expected Output¶
Successful Data Creation¶
╔════════════════════════════════════════════════════════════╗
║ SAVEDATA DEBUGGER - FULL DIAGNOSTIC ║
╚════════════════════════════════════════════════════════════╝
========================================
[SaveDataDebugger] Validating PlayerData (NewSave) - CreateNewPlayerData
========================================
[SaveDataDebugger] ✓ PlayerData object exists
[SaveDataDebugger] Version: 1.0.0
[SaveDataDebugger] SoulPoint: 0
[SaveDataDebugger] ChaosFragment: 0
[SaveDataDebugger] ✓ unlockedChar - Count: 10
[SaveDataDebugger] ✓ unlockedAchievement - Count: 0
[SaveDataDebugger] ✓ unlockedSpecialUpgrade - Count: 5
[SaveDataDebugger] ✓ shopUpgrade - Count: 8
[SaveDataDebugger] ✓ unlockedStage - Count: 20
[SaveDataDebugger] ✓ totalDataCounter - Count: 0
[SaveDataDebugger] ✓ All dictionaries are initialized
========================================
[SaveDataDebugger] Testing JSON serialization...
[SaveDataDebugger] ✓ JSON serialization successful
[SaveDataDebugger] JSON length: 1234 characters
[SaveDataDebugger] ✓ JSON deserialization successful
[SaveDataDebugger] ✗ unlockedAchievement became NULL after deserialization!
[SaveDataDebugger] This indicates Unity's JsonUtility cannot serialize Dictionaries properly!
╔════════════════════════════════════════════════════════════╗
║ DIAGNOSTIC COMPLETE ║
╚════════════════════════════════════════════════════════════╝
Null Dictionary Error¶
========================================
[SaveDataDebugger] Validating PlayerData (LoadedSave) - LoadNewEncryptedSave
========================================
[SaveDataDebugger] ✓ PlayerData object exists
[SaveDataDebugger] Version: 1.0.0
[SaveDataDebugger] SoulPoint: 100
[SaveDataDebugger] ChaosFragment: 50
[SaveDataDebugger] ✓ unlockedChar - Count: 10
[SaveDataDebugger] ✗ unlockedAchievement is NULL!
[SaveDataDebugger] ✓ unlockedSpecialUpgrade - Count: 5
[SaveDataDebugger] ✓ shopUpgrade - Count: 8
[SaveDataDebugger] ✓ unlockedStage - Count: 20
[SaveDataDebugger] ✓ totalDataCounter - Count: 15
[SaveDataDebugger] ✗ FOUND 1 NULL DICTIONARIES - This will cause issues!
========================================
Common Issues & Solutions¶
Issue 1: Dictionaries become null after JSON deserialization¶
Symptom: unlockedAchievement became NULL after deserialization!
Cause: Unity's JsonUtility cannot serialize Dictionary<TKey, TValue> types.
Solution: Use a custom JSON serializer (Newtonsoft.Json) or create wrapper classes for dictionaries.
Issue 2: Dictionaries are null in loaded save¶
Symptom: ✗ unlockedAchievement is NULL!
Cause: Save file was created before dictionary initialization was properly implemented.
Solution: Add migration code to handle null dictionaries by initializing them:
if (playerData.unlockedAchievement == null)
playerData.unlockedAchievement = new Dictionary<string, bool>();
Issue 3: Legacy save has null achievement data¶
Symptom: ⚠ unlockedAchievement is NULL in legacy save
Cause: Legacy save file doesn't contain achievement data or it was never initialized.
Solution: Ensure merge code handles null dictionaries gracefully:
if (legacy.unlockedAchievement != null)
{
MergeBoolDict(merged.unlockedAchievement, legacy.unlockedAchievement);
}
Usage Example¶
Adding Debugger to New Code¶
public void YourSaveMethod()
{
PlayerData data = CreateOrLoadData();
// Validate the data
SaveDataDebugger.RunFullDiagnostic(data, SaveDataDebugger.SaveDataType.LoadedSave, "YourMethod");
// Use the data
ProcessData(data);
}
Specific Validation¶
if (data != null)
{
// Check only achievement dictionary
if (data.unlockedAchievement == null)
{
Debug.LogError("Achievement dictionary is null!");
SaveDataDebugger.DebugPlayerData(data, SaveDataDebugger.SaveDataType.LoadedSave, "BeforeFix");
// Fix it
data.unlockedAchievement = new Dictionary<string, bool>();
}
}
Troubleshooting Guide¶
- Game crashes on startup
- Look for
PlayerData is NULLin logs - Check if PlayerData is being created before use
-
Verify
SaveManager.Instance.Playeris not null -
Achievements not loading
- Look for
unlockedAchievement is NULLafter loading - Check if JSON serialization is losing dictionary data
-
Verify save file contains achievement data
-
Save file corrupted
- Check encryption/decryption logs for mismatches
- Verify JSON length is reasonable
-
Check for null PlayerData after deserialization
-
Legacy migration fails
- Review
DebugLegacyDataoutput - Check if legacy saves are null
- Verify merge logic handles null dictionaries
Performance Considerations¶
The debugger adds logging overhead: - Use only during development/debugging - Remove or disable in production builds - Consider adding a compile-time flag to disable:
#if UNITY_EDITOR || DEVELOPMENT_BUILD
SaveDataDebugger.RunFullDiagnostic(playerData, SaveDataType.SaveDataType.NewSave, "context");
#endif
Future Enhancements¶
- Add validation for data ranges (e.g., negative soulPoint)
- Add checksum verification for save files
- Add timeline tracking of data changes
- Add export of diagnostic data to file
- Add automated fix suggestions for common issues