SOBackupRestore: salvataggio dati ScriptableObject di Unity Sei stanco di perdere dati durante i refactory dei tuoi ScriptableObject? Risolvi il problema con un tool di backup e ripristino pratico e facile da usare

Unity games with no audio on Windows - Obra Dinn, Hollow Knight and more - How to fix
Fork me on GitHub

SOBackupRestore è un’utility per Unity (solo Editor) che esegue il backup e il ripristino degli asset ScriptableObject come file JSON nominati con il loro GUID.

Riproduce la serializzazione dell’Inspector (campi, liste, enum, dati annidati e riferimenti a asset) e può opzionalmente rimappare i nomi dei campi (vecchio → nuovo) durante il ripristino, consentendo di rifattorizzare gli schemi e riportare comunque i valori negli asset esistenti senza toccare la pipeline di produzione.

Il codice sorgente completo e aggiornato è disponibile su GitHub sotto licenza MIT, il che significa che può essere utilizzato gratuitamente per qualsiasi scopo.

Ho creato SOBackupRestore perché ero stanco di vedere i dati accuratamente impostati nei miei ScriptableObject sparire dopo refactor apparentemente innocui — rinominare un campo, spostare una classe, riorganizzare namespace. Se sviluppi giochi ricchi di contenuti—o iteri in modo aggressivo—probabilmente conosci quella sensazione allo stomaco: il codice compila, l’Inspector sembra a posto… e i valori del tuo .asset sono misteriosamente scomparsi.

In questo articolo mostrerò cosa fa SOBackupRestore e come usarlo passo passo per proteggere i tuoi dati durante le rifattorizzazioni.

Il problema principale: Unity serializza per nome del campo

Il serializer di Unity si basa sui nomi dei campi. Se rinomini un [SerializeField] (o cambi tipo), gli asset esistenti non possono più corrispondere alle chiavi salvate. Unity non sa dove inserire quei dati, quindi vengono rimossi dall’Inspector.

Sì, esistono ottimi strumenti come [FormerlySerializedAs] e [MovedFrom]—e dovresti usarli—ma i progetti reali diventano complicati:

  • Stai lavorando su decine di tipi di ScriptableObject.
  • Alcuni campi cambiano più volte in vari sprint.
  • Qualcuno ha spostato classi tra assembly/namespace.
  • Hai bisogno di un modo garantito per procedere dopo una modifica di schema.

Volevo una chiave inglese nella cassetta degli attrezzi, da usare ogni volta che programmavo una rifattorizzazione rischiosa.

Cosa fa SOBackupRestore (in breve)

SOBackupRestore è un’utility solo Editor che:

  • Esegue il backup di ogni ScriptableObject trovato in un file JSON formattato in modo leggibile.
  • Nomina ogni file con il GUID dell’asset (non con il percorso), così spostare/rinominare asset è sicuro.
  • Ripristina i valori negli asset esistenti tramite EditorJsonUtility.FromJsonOverwrite.
  • Applica opzionalmente un semplice rimappaggio dei nomi dei campi (vecchiaChiave → nuovaChiave) durante il ripristino, permettendo di sopravvivere a rinominazioni aggressive anche senza aver annotato tutto con [FormerlySerializedAs].

Risultato: puoi rifattorizzare con fiducia e poi riportare i tuoi dati negli asset.

Quando usarlo

  • Prima di grandi rifattorizzazioni degli schemi ScriptableObject.
  • Quando unisci branch di contenuti in cui i nomi dei campi divergono.
  • Come passo di migrazione leggero insieme a [FormerlySerializedAs]/[MovedFrom].
  • Quando nuovi membri del team riorganizzano cartelle di progetto e nomi di asset.

Non sostituisce buone pratiche—è una cintura di sicurezza che mi permette di muovermi più velocemente.

Come funziona (dietro le quinte)

  • Backup: Per ogni ScriptableObject trovato nelle cartelle selezionate, lo strumento scrive un {guid}.json contenente l’esatta serializzazione in stile Inspector (liste, enum, dati annidati, riferimenti come {fileID, guid, type}, anche molti casi di SerializeReference).
  • Ripristino: Per ogni *.json, risolve il GUID al percorso dell’asset, carica lo ScriptableObject, riscrive opzionalmente le chiavi dei campi nel JSON (replace stringa su "fieldName":), e chiama FromJsonOverwrite per ripopolare i valori. Gli asset vengono marcati come dirty; non viene creato nulla di nuovo.

Poiché tutto è basato sul GUID, gli spostamenti di percorso non rompono la corrispondenza.

Guida rapida (workflow Editor)

  1. Metti lo script in una cartella Editor. Qualsiasi percorso .../Editor/ funziona (es. Assets/Tools/Editor/SOBackupRestore.cs). Deve essere solo Editor.
  2. Backup: Nella Project window, seleziona le cartelle desiderate (o non selezionare nulla per scansionare tutto Assets/). Usa il menu: Tools → Contrappasso → Backup ScriptableObjects to JSON…. Scegli una cartella di output (conservo i backup fuori da Assets/).
  3. Rifattorizza: Rinomina campi/classi/namespace liberamente. Aggiungi [FormerlySerializedAs]/[MovedFrom] dove possibile.
  4. (Opzionale) Mappa i nomi dei campi: Apri SOBackupRestore e compila il dizionario keyRenames (vedi sotto).
  5. Ripristino: Tools → Contrappasso → Restore ScriptableObjects from JSON…. Indica la tua cartella di backup. Guarda i valori tornare negli asset.

Consiglio: Fai commit prima e dopo. I JSON sono ottimi breadcrumb forensi nei code review.

Rimappaggio nomi dei campi (opzionale ma potente)

Inserisci le mappature vecchio → nuovo in un dizionario prima del ripristino. Lo strumento riscriverà le chiavi JSON e poi sovrascriverà i valori negli asset.

È una valvola di sicurezza pragmatica quando non puoi annotare ogni campo rinominato (es. progetti con più team, branch legacy multipli). Riscrive solo le chiavi JSON (la parte sinistra di "key": value), mantenendo intatti i valori.

Best practice da seguire insieme a SOBackupRestore

  • Tieni visibili i file .meta e imposta la serializzazione su Force Text (Project Settings → Editor).
  • Preferisci campi privati serializzati + proprietà pubbliche per ridurre futuri rinomini di campi serializzati.
  • Aggiungi [FormerlySerializedAs] ai campi rinominati e lasciali per un paio di release.
  • Usa [MovedFrom] quando cambi nomi di classi/namespace/assembly.
  • Durante grandi migrazioni, esegui un backup, poi un ripristino, quindi apri alcuni asset/scenes “sentinella” e verifica i valori a occhio.

Limitazioni (conoscile, evita sorprese)

  • Copre solo dati serializzabili da Unity (pubblici o [SerializeField]). Non campi statici, non proprietà calcolate.
  • Sovrascrive i valori sugli asset esistenti; non crea nuovi asset.
  • Se cambi i tipi in modo incompatibile, Unity non può deserializzare i vecchi valori. Usa codice di migrazione (ISerializationCallbackReceiver) per vere modifiche di schema.

Perché JSON, non strumenti custom?

  • Il JSON è trasparente—diffabile, ricercabile, facile da correggere.
  • EditorJsonUtility rispecchia ciò che fa l’Inspector. Nessuna sorpresa, nessun formatter custom da mantenere.
  • I backup possono vivere fuori dall’albero del progetto, così non contaminano build o CI.

Considerazioni finali

SOBackupRestore non rende le rifattorizzazioni banali—ma toglie la paura. L’ho creato per muovermi più velocemente su Contrappasso senza rischiare ore di lavoro nascosto negli ScriptableObject. Se gestisci molti contenuti e iteri in modo intenso, prova questo workflow. Combinalo con buone pratiche di serializzazione e dormirai meglio la prossima volta che rinomini damage in baseDamage cinque minuti prima di una milestone.

Se vuoi, posso condividere un template “starter” semplificato (voci di menu + UI minima) o una versione che prende di mira un tipo specifico (es. solo WeaponData) e genera un CSV di confronto prima/dopo per controlli rapidi.

About Ryan

IT Project Manager, Web Interface Architect e Lead Developer di numerosi siti e servizi web ad alto traffico in Italia e in Europa. Dal 2010 si occupa anche della progettazione di App e giochi per dispositivi Android, iOS e Mobile Phone per conto di numerose società italiane. Microsoft MVP for Development Technologies dal 2018.

View all posts by Ryan

Leave a Reply

Your email address will not be published. Required fields are marked *


Il periodo di verifica reCAPTCHA è scaduto. Ricaricare la pagina.

Questo sito utilizza Akismet per ridurre lo spam. Scopri come vengono elaborati i dati derivati dai commenti.