Perdere ore di gioco per un salvataggio corrotto è una delle esperienze più frustranti per un giocatore, e una delle recensioni negative più facili da evitare per uno sviluppatore. Un sistema di salvataggio affidabile va progettato presto, perché influenza il modo in cui si organizzano i dati di tutto il gioco.
Che cosa salvare davvero
L'errore più comune è cercare di salvare «tutto», serializzando interi oggetti del motore con riferimenti, texture e stato interno. Il risultato è fragile, pesante e si rompe al primo aggiornamento. Conviene invece distinguere:
- dati statici: livelli, statistiche dei nemici, descrizioni degli oggetti. Fanno parte del gioco e non vanno salvati;
- stato persistente: ciò che il giocatore ha cambiato, cioè livello attuale, posizione, inventario, missioni completate, porte aperte, nemici unici sconfitti, impostazioni.
Il salvataggio contiene solo il secondo gruppo, espresso con dati semplici: numeri, stringhe, elenchi, identificatori. Un oggetto dell'inventario si salva come "spada_ferro" con una quantità, non come l'intero oggetto con il suo sprite.
Identificatori stabili
Per ricordare che un forziere è stato aperto, ogni elemento persistente del mondo deve avere un identificatore univoco e stabile, che non cambi se il livello viene modificato. Usare l'indice dell'oggetto in una lista è rischioso: aggiungendo un forziere nella nuova versione, tutti gli indici successivi si spostano e i salvataggi esistenti diventano incoerenti.
Formati: testo o binario
| Formato | Vantaggi | Svantaggi |
|---|---|---|
| JSON o simili | Leggibile, facile da ispezionare e correggere | Più voluminoso, modificabile dai giocatori |
| Binario personalizzato | Compatto, veloce da leggere | Difficile da analizzare, versioni più delicate |
| Database incorporato | Ottimo per molti dati e salvataggi parziali | Complessità aggiuntiva |
Per la maggior parte dei giochi un formato testuale come JSON, eventualmente compresso, è un'ottima scelta. Durante lo sviluppo poter aprire un salvataggio con un editor di testo fa risparmiare molto tempo. Il fatto che i giocatori possano modificarlo è un problema solo nei giochi competitivi online, dove comunque lo stato importante deve risiedere sul server.
Versioni dei salvataggi
Il gioco cambierà dopo l'uscita: nuove funzioni, oggetti rinominati, sistemi ripensati. I salvataggi creati con la versione precedente devono continuare a funzionare. La regola è semplice: ogni file contiene un numero di versione.
{
"versione": 3,
"livello": "foresta_02",
"salute": 74,
"inventario": [{"id": "pozione", "quantita": 3}]
}
Al caricamento, se la versione è vecchia, si applicano in sequenza le migrazioni: da 1 a 2 si aggiunge un campo con un valore predefinito, da 2 a 3 si rinomina un identificatore. Ogni migrazione è una piccola funzione che trasforma i dati, e restano tutte nel codice. In questo modo un salvataggio di molte versioni fa viene aggiornato passo per passo.
Altri accorgimenti utili:
- ignorare i campi sconosciuti invece di generare un errore;
- usare valori predefiniti sensati per i campi mancanti;
- non rimuovere mai la capacità di leggere una versione già pubblicata.
Scrivere senza corrompere
Se il gioco si chiude, il sistema va in sospensione o manca la corrente durante la scrittura, il file può restare a metà. Un procedimento robusto:
- scrivere il salvataggio in un file temporaneo;
- assicurarsi che i dati siano effettivamente su disco;
- rinominare il file temporaneo al posto di quello vecchio, operazione che sulla maggior parte dei file system è atomica;
- conservare una o due copie di backup delle versioni precedenti.
Al caricamento si verifica l'integrità, per esempio con una somma di controllo salvata insieme ai dati. Se il file principale è danneggiato, si propone il backup più recente invece di cancellare i progressi.
Quando salvare
Le scelte di design incidono anche sulla tecnica:
- punti di salvataggio fissi: lo stato da salvare è prevedibile e limitato;
- salvataggio libero: bisogna poter serializzare lo stato in qualsiasi momento, anche a metà di un combattimento, con proiettili in volo e nemici in movimento;
- salvataggio automatico: va fatto in momenti tranquilli, come cambi di livello o fine di un dialogo, e su uno slot separato, per non sovrascrivere un salvataggio manuale.
Salvare durante il gioco può causare piccoli scatti. Si raccolgono i dati velocemente nel thread principale e si delega la scrittura su disco a un thread secondario, mostrando un'icona che avvisa di non spegnere.
Dove salvare
Ogni sistema operativo prevede cartelle specifiche per i dati delle applicazioni dell'utente. Scrivere nella cartella di installazione del gioco è una cattiva idea: spesso non si hanno i permessi, e un aggiornamento o una reinstallazione potrebbe cancellare tutto. I motori offrono funzioni che restituiscono il percorso corretto per ogni piattaforma. Sulle piattaforme con salvataggi nel cloud, il formato compatto e le versioni diventano ancora più importanti.
Testare il sistema
Il sistema di salvataggio va trattato come una funzione critica: test automatici che salvano e ricaricano lo stato verificando che coincida, una raccolta di salvataggi di ogni versione pubblicata da caricare a ogni nuova build, prove di interruzione durante la scrittura.
In sintesi
- Si salva solo lo stato persistente, con dati semplici e identificatori stabili.
- JSON è spesso la scelta più pratica; il binario serve quando contano dimensioni e velocità.
- Ogni file ha un numero di versione e le migrazioni aggiornano i vecchi salvataggi.
- File temporaneo, rinomina atomica e backup evitano corruzioni.
- Salvataggi automatici in momenti tranquilli e cartelle di sistema corrette completano il quadro.