Come salvare e caricare i progressi dei tuoi giocatori in Unity

Cosa starai creando

In questo tutorial, imparerai come implementare un semplice sistema per creare e gestire i salvataggi per i tuoi giochi Unity. Costruiremo il quadro per a Fantasia finale-come il menu principale che consente ai giocatori di creare nuovi file di salvataggio unici e di caricare quelli esistenti. I principi dimostrati ti permetteranno di estenderli a qualunque necessità abbia il tuo gioco. 

Alla fine del tutorial, avrai imparato come:

  • salva e carica i dati di gioco all'interno di Unity3D utilizzando la serializzazione
  • usa le variabili statiche per mantenere i dati attraverso i cambiamenti di scena

Nota: questo approccio al salvataggio e caricamento dei dati di gioco funziona su tutte le piattaforme ad eccezione del Web Player. Per informazioni sul salvataggio dei dati di gioco in Web Player, dai un'occhiata ai documenti ufficiali su Unity Web Player e sulla comunicazione del browser.

Prendiamo Serial

La prima cosa che faremo è creare un codice che ci consenta di serializzare i nostri dati di gioco, ovvero convertirli in un formato che può essere salvato e successivamente ripristinato. Per questo, creiamo uno script C # e chiamiamolo SaveLoad. Questo script gestirà tutte le funzionalità di salvataggio e caricamento. 

Faremo riferimento a questo script da altri script, quindi rendiamolo una classe statica aggiungendo la parola statico fra pubblico e classe. Rimuoviamo anche il : MonoBehaviour parte, perché non abbiamo bisogno di collegarlo a un GameObject. E dal momento che non eredita più da MonoBehaviour, cancelliamo il Inizio e Aggiornare funzioni. 

Il codice risultante dovrebbe assomigliare a questo:

usando UnityEngine; usando System.Collections; classe statica pubblica SaveLoad 

Ora, vorremmo aggiungere alcune nuove funzionalità a questo script, quindi immediatamente sotto dove dice usando System.Collections;, aggiungere il seguente:

using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO;

La prima riga ci consente di utilizzare elenchi dinamici in C #, ma questo non è necessario per la serializzazione. La seconda linea è ciò che ci consente di utilizzare le funzionalità di serializzazione del sistema operativo all'interno dello script. Nella terza riga, IO sta per Input Output, ed è ciò che ci permette di scrivere e leggere dal nostro computer o dispositivo mobile. In altre parole, questa linea ci consente di creare file univoci e quindi di leggere successivamente quei file.

Ora siamo pronti per serializzare alcuni dati!

Fare classi serializzabili

Ora che il nostro script ha la possibilità di serializzare, dovremo impostare alcune classi da serializzare. Se pensi a un gioco di ruolo di base, come Fantasia finale, offre ai giocatori la possibilità di creare e caricare diversi giochi salvati. Quindi, creare un nuovo script C # chiamato Giocoe dargli alcune variabili per contenere tre oggetti: a cavaliere, un furfante, e a procedura guidata. Cambia il codice di questo script per assomigliare a questo:

usando UnityEngine; usando System.Collections; [System.Serializable] Gioco di classe pubblica Corrente di gioco statica pubblica; personaggio pubblico cavaliere; personaggio pubblico canaglia; wizard dei personaggi pubblici; public Game () knight = new Character (); rogue = new Character (); wizard = new Character (); 

Il [System.Serializable] line dice a Unity che questo script può essere serializzato-in altre parole, possiamo salvare tutte le variabili in questo script. Freddo! Secondo i documenti ufficiali, Unity può serializzare i seguenti tipi:

  • Tutti i tipi di dati di base (come int, stringa, galleggiante, e bool).
  • Alcuni tipi built-in (incluso Vector2, Vector3, vector4, quaternion, Matrix4x4, Colore, Rect, e LayerMask).
  • Tutte le classi ereditano da UnityEngine.Object (Compreso GameObject, Componente, MonoBehavior, Texture2D, e AnimationClip).
  • Enums.
  • Array ed elenchi di un tipo serializzabile.

La prima variabile, attuale, è un riferimento statico a a Gioco esempio. Quando creiamo o cariciamo un gioco, imposteremo questa variabile statica su quella particolare istanza di gioco in modo da poter fare riferimento al "gioco corrente" da qualsiasi punto del progetto. Usando variabili e funzioni statiche, non dobbiamo usare a gameObject'S GetComponent () funzione. Maneggevole! 

Si noti che fa riferimento a qualcosa chiamato a Personaggio? Non ce l'abbiamo ancora, quindi creiamo un nuovo script per ospitare questo corso e chiamalo Personaggio:

usando UnityEngine; usando System.Collections; [System.Serializable] Carattere di classe pubblica nome di stringa pubblico; public Character () this.name = ""; 

Forse ti starai chiedendo perché abbiamo bisogno di una nuova classe se stiamo semplicemente memorizzando una variabile stringa. In effetti, potremmo semplicemente sostituire Personaggio nel Gioco script da usare stringa anziché. Ma voglio mostrarti quanto può essere profonda questa tana del coniglio: puoi salvare e caricare classi che fanno riferimento ad altre classi, e così via, purché ogni classe è serializzabile

Ora che le nostre classi sono impostate per essere salvate e caricate, torniamo al nostro SaveLoad script e aggiungere la possibilità di salvare i giochi.

Salvare lo stato di un gioco

Un menu "Carica partita" di solito mostra un elenco di giochi salvati, quindi creiamo un Elenco di tipo Gioco e chiamalo savedGames. Fatelo a Elenco statico, in modo che nel nostro progetto ci sia una sola lista di giochi salvati. Il codice dovrebbe assomigliare a questo:

usando UnityEngine; usando System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; public static class SaveLoad elenco statico pubblico savedGames = new List(); 

Quindi, creiamo una nuova funzione statica per salvare un gioco:

 public static void Save () savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); File FileStream = File.Create (Application.persistentDataPath + "/savedGames.gd"); bf.Serialize (file, SaveLoad.savedGames); File.Close ();  

La riga 2 aggiunge il nostro gioco attuale alla nostra lista di partite salvate. Quella lista è ciò che stiamo per serializzare. Per fare ciò, dobbiamo prima creare un nuovo BinaryFormatter, che gestirà il lavoro di serializzazione. Questo è ciò che fa la linea 3.

Nella linea 4, stiamo creando un FileStream, che è essenzialmente un percorso per un nuovo file che possiamo anche inviare dati, come il pesce che nuota a valle in un fiume. Noi usiamo File.Create () per creare un nuovo file nella posizione in cui passiamo come parametro. Convenientemente, Unity ha una posizione integrata per archiviare i nostri file di gioco (che si aggiorna automaticamente in base alla piattaforma su cui è costruito il gioco) che possiamo fare riferimento usando Application.persistentDataPath

Poiché stiamo creando un nuovo file, tuttavia, non possiamo solo dire dove si trova il file, ma dobbiamo anche chiudere questo percorso con il nome del file stesso. Ci sono due parti in questo file:

  1. il nome del file
  2. il tipo di file

Useremo savedGames per il nome del file, e useremo un tipo di dati personalizzato gd (per "dati di gioco") per il tipo di file. Il nostro risultato è un file di gioco chiamato savedGames.gd nella posizione impostata da Application.persistentDataPath. (In futuro, potresti salvare altri tipi di cose con questo tipo di dati, ad esempio, potresti salvare le impostazioni delle opzioni degli utenti come options.gd.)

Nota: Puoi rendere il tipo di file tutto ciò che desideri. Ad esempio, la serie di Elder Scrolls utilizza .ESM come il suo tipo di file. Avresti potuto facilmente dire savedGames.baconAndGravy.

Nella riga 5, stiamo chiamando il serializzare funzionalità del BinaryFormatter per salvare i nostri savedGames elenca il nostro nuovo file. Dopodiché, abbiamo chiuso il file che abbiamo creato, nella Line 6. 

Badda bing, boom di badda. I nostri giochi sono salvati.

Caricamento dello stato di un gioco

Nel Salvare funzione, abbiamo serializzato la nostra lista di giochi salvati in una posizione specifica. Al contrario, il codice per caricare i nostri giochi dovrebbe assomigliare a questo:

 public static void Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); File FileStream = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Elenco) Bf.Deserialize (file); File.Close (); 

Nella riga 2, controlliamo se esiste un file di gioco salvato. (In caso contrario, non ci sarà nulla da caricare, ovviamente.) Nella Linea 3, creiamo a BinaryFormatter allo stesso modo che abbiamo fatto nel Salvare funzione. Nella linea 4, creiamo a FileStream-ma questa volta i nostri pesci nuotano controcorrente dal file. Quindi, usiamo File.Aperto, e indica dove siamo savedGames.gd esiste usando lo stesso Application.persistentDataPath stringa. 

La linea 5 è un po 'densa, quindi scompattiamola: 

  • Il bf.Deserialize (file) call trova il file nel percorso specificato sopra e lo deserializza. 
  • Non possiamo semplicemente sputare binari su Unity e aspettarci che funzioni, tuttavia, così noi convertire (o trasmettere) il nostro file deserializzato al tipo di dati che vogliamo che sia, che in questo caso è a Elenco di tipo Gioco. 
  • Quindi impostiamo questa lista come la nostra lista di giochi salvati. 

Infine, nella Linea 6, chiudiamo quel file nello stesso modo in cui lo abbiamo fatto noi Salvare funzione. 

Nota: Il tipo di dati a cui vengono trasmessi i dati deserializzati può variare in base a ciò che è necessario che sia. Per esempio, Player.lives = (int) bf.Deserialize (file);.

Conclusione

Nostro SaveLoad lo script è ora completo e dovrebbe avere questo aspetto:

usando UnityEngine; usando System.Collections; using System.Collections.Generic; using System.Runtime.Serialization.Formatters.Binary; using System.IO; public static class SaveLoad elenco statico pubblico savedGames = new List(); // è statico quindi possiamo chiamarlo da qualsiasi posizione public static void Save () SaveLoad.savedGames.Add (Game.current); BinaryFormatter bf = new BinaryFormatter (); //Application.persistentDataPath è una stringa, quindi se lo si desidera è possibile inserirlo in debug.log se si desidera sapere dove si trovano i file di salvataggio FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); // puoi chiamarlo tutto ciò che vuoi bf.Serialize (file, SaveLoad.savedGames); File.Close ();  public static void Load () if (File.Exists (Application.persistentDataPath + "/savedGames.gd")) BinaryFormatter bf = new BinaryFormatter (); File FileStream = File.Open (Application.persistentDataPath + "/savedGames.gd", FileMode.Open); SaveLoad.savedGames = (Elenco) Bf.Deserialize (file); File.Close ();  

Queste sono le basi del salvataggio e del caricamento in Unity. Nel file di progetto allegato, troverai alcuni altri script che mostrano come gestisco la chiamata di queste funzioni e come visualizzo i dati utilizzando la GUI di Unity.

Se hai bisogno di un vantaggio con lo sviluppo del tuo gioco, prova i modelli Unity3D disponibili su Envato Market.