Unity Save System
Ce que fait cette skill
Guider l'implementation d'un systeme de sauvegarde complet pour Unity 6+ : serialisation de l'etat de jeu, persistence fichier avec ecriture atomique, versioning des donnees sauvegardees, gestion multi-slots, auto-save, cloud saves (UGS), et encryption optionnelle. Couvre du simple PlayerPrefs jusqu'aux architectures hybrides local/cloud.
Prerequis
- Unity 6.0+ (Awaitable API)
- Recommande : Newtonsoft.Json (
com.unity.nuget.newtonsoft-json) pour serialisation avancee
- Aucune dependance stricte pour les cas simples (JsonUtility suffit)
Demarrage rapide
- Choisir le format : JsonUtility (simple) ou Newtonsoft.Json (polymorphisme, Dictionary)
- Creer l'interface
ISaveable sur chaque composant a sauvegarder
- Implementer
SaveManager avec ecriture atomique dans Application.persistentDataPath
- Brancher l'auto-save (dirty flag + timer +
OnApplicationPause)
- Tester le cycle save/load avec un test EditMode (voir
/unity-test)
Arbre de decision
Que sauvegarder ?
|
+-- Preferences utilisateur (volume, langue, bindings) ?
| +-- Peu de donnees (<1 KB) --> PlayerPrefs
| +-- Plus structure ----------> JSON dans persistentDataPath
|
+-- Etat de jeu (progression, inventaire, position) ?
| +-- Slot unique -----------> JSON + ISaveable pattern
| +-- Multi-slots -----------> SaveManager avec index + slots nommes
| +-- Donnees volumineuses (>10 MB) --> Format binaire (MemoryPack/MessagePack)
|
+-- Cloud sync ?
| +-- Unity Gaming Services --> UGS Cloud Save
| +-- Cross-platform natif --> Platform Toolkit (Unity 6.3+)
| +-- Hybride (local + cloud) -> ISaveStorage abstraction (voir `references/save-advanced.md`)
|
+-- Sensible (anti-cheat) ?
+-- Encryption AES + hash d'integrite (voir `references/save-advanced.md`)
Guide etape par etape
Etape 1 — Choisir le format de serialisation
| Critere |
JsonUtility |
Newtonsoft.Json |
MemoryPack |
MessagePack |
| Setup |
Inclus Unity |
Package Unity |
NuGet |
NuGet |
| Polymorphisme |
Non |
Oui (TypeNameHandling) |
Oui |
Oui |
| Dictionary |
Non |
Oui |
Oui |
Oui |
| Lisibilite |
JSON |
JSON |
Binaire |
Binaire |
| Performance |
Rapide |
Moyen |
Tres rapide |
Rapide |
| Taille |
Moyen |
Moyen |
Petit |
Petit |
| Recommandation |
Prototypage |
Defaut recommande |
>10 MB donnees |
Alternative binaire |
Etape 2 — Creer ISaveable et SaveData
- Definir
ISaveable : SaveKey, CaptureState(), RestoreState(object)
- Creer
SaveData avec champ version, Dictionary<string, object>, metadata
- Voir
references/save-templates.md pour le code complet (ISaveable, SaveData, SaveManager)
Etape 3 — Implementer SaveManager
- Pattern singleton ou service locator (voir
/unity architecture)
- Registry de
ISaveable (Register/Unregister)
SaveAsync : capturer tous les etats -> serialiser -> ecriture atomique (.tmp -> .save, .bak)
LoadAsync : lire fichier -> deserialiser -> restaurer tous les etats
- Chemin :
Path.Combine(Application.persistentDataPath, "saves", slotName + ".save")
Etape 4 — Auto-save
- Dirty flag : chaque
ISaveable signale ses changements
- Timer configurable (60-120s par defaut)
- Sauvegarder sur
OnApplicationPause(true) et changement de scene
- Voir
references/save-advanced.md section Auto-Save
Etape 5 — Tester le cycle save/load
- Test EditMode : save -> clear state -> load -> assert state restored
- Test corruption : charger un fichier tronque -> verifier fallback .bak
- Test migration : charger une save v1 avec du code v2
Regles strictes
TOUJOURS
- TOUJOURS utiliser l'ecriture atomique (write .tmp, rename, keep .bak)
- TOUJOURS versionner les
SaveData (champ version incremente a chaque changement de schema)
- TOUJOURS utiliser
Application.persistentDataPath (jamais dataPath ou streamingAssetsPath)
- TOUJOURS sauvegarder sur
OnApplicationPause(true) pour mobile
- TOUJOURS serialiser des POCOs (Plain Old C# Objects) — pas de types Unity
- TOUJOURS gerer le cas "pas de sauvegarde" (premier lancement)
JAMAIS
- JAMAIS utiliser
BinaryFormatter — faille de securite connue, deprecie
- JAMAIS stocker de references
MonoBehaviour, GameObject, ou ScriptableObject dans les saves
- JAMAIS sauvegarder sur le thread principal de facon synchrone pour des fichiers >100 KB
- JAMAIS supprimer l'ancien fichier avant que le nouveau soit ecrit (corruption garantie en cas de crash)
- JAMAIS ignorer les exceptions d'I/O — toujours try/catch avec fallback
Skills connexes
/unity-code-gen — Generer le boilerplate ISaveable et SaveManager
/unity-test — Tests EditMode pour valider le cycle save/load
/unity-debug — Diagnostiquer les problemes de deserialisation
/addressables — Sauvegarder les references d'assets par address string
Troubleshooting
| Probleme |
Cause probable |
Solution |
FileNotFoundException au load |
Premier lancement, aucune save |
Verifier File.Exists() avant load, retourner donnees par defaut |
| Donnees perdues apres mise a jour |
Schema change sans migration |
Ajouter champ version + chaine de migration v1->v2->vN |
JsonSerializationException |
Type polymorphe non reconnu |
Newtonsoft : TypeNameHandling.Auto + SerializationBinder custom |
| Save corrompue (JSON tronque) |
Crash pendant ecriture |
Ecriture atomique (.tmp -> rename) + fallback sur .bak |
UnauthorizedAccessException |
Chemin non autorise (Android scope) |
Utiliser uniquement persistentDataPath |
| PlayerPrefs disparaissent (iOS) |
Nettoyage systeme ou reinstallation |
Migrer vers fichier pour donnees importantes |
| Save trop volumineuse (>50 MB) |
Serialisation JSON de gros volumes |
Passer a MemoryPack/MessagePack, compresser (GZip) |
| Desync cloud/local |
Conflit de versions |
Implementer conflict resolution (timestamp ou version counter) |
1---2name: unity-save-system3description: Implementer un systeme de sauvegarde et persistence : /unity-save, /save, sauvegarde, save system, persistence, sauvegarder, charger une partie, save game, PlayerPrefs, serialisation, JSON save, cloud save, slot de sauvegarde4---5
6# Unity Save System
7
8## Ce que fait cette skill
9
10Guider l'implementation d'un systeme de sauvegarde complet pour Unity 6+ : serialisation de l'etat de jeu, persistence fichier avec ecriture atomique, versioning des donnees sauvegardees, gestion multi-slots, auto-save, cloud saves (UGS), et encryption optionnelle. Couvre du simple PlayerPrefs jusqu'aux architectures hybrides local/cloud.
11
12## Prerequis
13
14- Unity 6.0+ (Awaitable API)
15- **Recommande** : Newtonsoft.Json (`com.unity.nuget.newtonsoft-json`) pour serialisation avancee
16- Aucune dependance stricte pour les cas simples (JsonUtility suffit)
17
18## Demarrage rapide
19
201. **Choisir le format** : JsonUtility (simple) ou Newtonsoft.Json (polymorphisme, Dictionary)
212. **Creer l'interface** `ISaveable` sur chaque composant a sauvegarder
223. **Implementer** `SaveManager` avec ecriture atomique dans `Application.persistentDataPath`
234. **Brancher** l'auto-save (dirty flag + timer + `OnApplicationPause`)
245. **Tester** le cycle save/load avec un test EditMode (voir `/unity-test`)
25
26## Arbre de decision
27
28```
29Que sauvegarder ?
30|
31+-- Preferences utilisateur (volume, langue, bindings) ?
32| +-- Peu de donnees (<1 KB) --> PlayerPrefs
33| +-- Plus structure ----------> JSON dans persistentDataPath
34|
35+-- Etat de jeu (progression, inventaire, position) ?
36| +-- Slot unique -----------> JSON + ISaveable pattern
37| +-- Multi-slots -----------> SaveManager avec index + slots nommes
38| +-- Donnees volumineuses (>10 MB) --> Format binaire (MemoryPack/MessagePack)
39|
40+-- Cloud sync ?
41| +-- Unity Gaming Services --> UGS Cloud Save
42| +-- Cross-platform natif --> Platform Toolkit (Unity 6.3+)
43| +-- Hybride (local + cloud) -> ISaveStorage abstraction (voir `references/save-advanced.md`)
44|
45+-- Sensible (anti-cheat) ?
46 +-- Encryption AES + hash d'integrite (voir `references/save-advanced.md`)
47```
48
49## Guide etape par etape
50
51### Etape 1 — Choisir le format de serialisation
52
53| Critere | JsonUtility | Newtonsoft.Json | MemoryPack | MessagePack |
54|---------|------------|-----------------|------------|-------------|
55| Setup | Inclus Unity | Package Unity | NuGet | NuGet |
56| Polymorphisme | Non | Oui (`TypeNameHandling`) | Oui | Oui |
57| Dictionary | Non | Oui | Oui | Oui |
58| Lisibilite | JSON | JSON | Binaire | Binaire |
59| Performance | Rapide | Moyen | Tres rapide | Rapide |
60| Taille | Moyen | Moyen | Petit | Petit |
61| Recommandation | Prototypage | **Defaut recommande** | >10 MB donnees | Alternative binaire |
62
63### Etape 2 — Creer ISaveable et SaveData
64
65- Definir `ISaveable` : `SaveKey`, `CaptureState()`, `RestoreState(object)`
66- Creer `SaveData` avec champ `version`, `Dictionary<string, object>`, metadata
67- Voir `references/save-templates.md` pour le code complet (ISaveable, SaveData, SaveManager)
68
69### Etape 3 — Implementer SaveManager
70
71- Pattern singleton ou service locator (voir `/unity` architecture)
72- Registry de `ISaveable` (Register/Unregister)
73- `SaveAsync` : capturer tous les etats -> serialiser -> ecriture atomique (.tmp -> .save, .bak)
74- `LoadAsync` : lire fichier -> deserialiser -> restaurer tous les etats
75- Chemin : `Path.Combine(Application.persistentDataPath, "saves", slotName + ".save")`
76
77### Etape 4 — Auto-save
78
79- Dirty flag : chaque `ISaveable` signale ses changements
80- Timer configurable (60-120s par defaut)
81- Sauvegarder sur `OnApplicationPause(true)` et changement de scene
82- Voir `references/save-advanced.md` section Auto-Save
83
84### Etape 5 — Tester le cycle save/load
85
86- Test EditMode : save -> clear state -> load -> assert state restored
87- Test corruption : charger un fichier tronque -> verifier fallback .bak
88- Test migration : charger une save v1 avec du code v2
89
90## Regles strictes
91
92### TOUJOURS
93
94- **TOUJOURS** utiliser l'ecriture atomique (write .tmp, rename, keep .bak)
95- **TOUJOURS** versionner les `SaveData` (champ `version` incremente a chaque changement de schema)
96- **TOUJOURS** utiliser `Application.persistentDataPath` (jamais `dataPath` ou `streamingAssetsPath`)
97- **TOUJOURS** sauvegarder sur `OnApplicationPause(true)` pour mobile
98- **TOUJOURS** serialiser des POCOs (Plain Old C# Objects) — pas de types Unity
99- **TOUJOURS** gerer le cas "pas de sauvegarde" (premier lancement)
100
101### JAMAIS
102
103- **JAMAIS** utiliser `BinaryFormatter` — faille de securite connue, deprecie
104- **JAMAIS** stocker de references `MonoBehaviour`, `GameObject`, ou `ScriptableObject` dans les saves
105- **JAMAIS** sauvegarder sur le thread principal de facon synchrone pour des fichiers >100 KB
106- **JAMAIS** supprimer l'ancien fichier avant que le nouveau soit ecrit (corruption garantie en cas de crash)
107- **JAMAIS** ignorer les exceptions d'I/O — toujours try/catch avec fallback
108
109## Skills connexes
110
111- `/unity-code-gen` — Generer le boilerplate ISaveable et SaveManager
112- `/unity-test` — Tests EditMode pour valider le cycle save/load
113- `/unity-debug` — Diagnostiquer les problemes de deserialisation
114- `/addressables` — Sauvegarder les references d'assets par address string
115
116## Troubleshooting
117
118| Probleme | Cause probable | Solution |
119|----------|---------------|----------|
120| `FileNotFoundException` au load | Premier lancement, aucune save | Verifier `File.Exists()` avant load, retourner donnees par defaut |
121| Donnees perdues apres mise a jour | Schema change sans migration | Ajouter champ `version` + chaine de migration v1->v2->vN |
122| `JsonSerializationException` | Type polymorphe non reconnu | Newtonsoft : `TypeNameHandling.Auto` + `SerializationBinder` custom |
123| Save corrompue (JSON tronque) | Crash pendant ecriture | Ecriture atomique (.tmp -> rename) + fallback sur .bak |
124| `UnauthorizedAccessException` | Chemin non autorise (Android scope) | Utiliser uniquement `persistentDataPath` |
125| PlayerPrefs disparaissent (iOS) | Nettoyage systeme ou reinstallation | Migrer vers fichier pour donnees importantes |
126| Save trop volumineuse (>50 MB) | Serialisation JSON de gros volumes | Passer a MemoryPack/MessagePack, compresser (GZip) |
127| Desync cloud/local | Conflit de versions | Implementer conflict resolution (timestamp ou version counter) |