Un modo ideale per memorizzare variabili tra le scene è attraverso una classe manager singleton. Creando una classe per l'archiviazione di dati persistenti e impostandola su DoNotDestroyOnLoad()
, puoi assicurarti che sia immediatamente accessibile e persista tra le scene.
Un'altra opzione che hai è usare la PlayerPrefs
classe. PlayerPrefs
è progettato per consentire di salvare i dati tra le sessioni di gioco , ma servirà comunque come mezzo per salvare i dati tra le scene .
Utilizzando una classe singleton e DoNotDestroyOnLoad()
Lo script seguente crea una classe singleton persistente. Una classe singleton è una classe progettata per eseguire solo una singola istanza contemporaneamente. Fornendo tale funzionalità, possiamo tranquillamente creare un riferimento automatico statico, per accedere alla classe da qualsiasi luogo. Ciò significa che puoi accedere direttamente alla classe con DataManager.instance
, comprese le variabili pubbliche all'interno della classe.
using UnityEngine;
/// <summary>Manages data for persistance between levels.</summary>
public class DataManager : MonoBehaviour
{
/// <summary>Static reference to the instance of our DataManager</summary>
public static DataManager instance;
/// <summary>The player's current score.</summary>
public int score;
/// <summary>The player's remaining health.</summary>
public int health;
/// <summary>The player's remaining lives.</summary>
public int lives;
/// <summary>Awake is called when the script instance is being loaded.</summary>
void Awake()
{
// If the instance reference has not been set, yet,
if (instance == null)
{
// Set this instance as the instance reference.
instance = this;
}
else if(instance != this)
{
// If the instance reference has already been set, and this is not the
// the instance reference, destroy this game object.
Destroy(gameObject);
}
// Do not destroy this object, when we load a new scene.
DontDestroyOnLoad(gameObject);
}
}
Puoi vedere il singleton in azione, sotto. Si noti che non appena eseguo la scena iniziale, l'oggetto DataManager si sposta dall'intestazione specifica della scena all'intestazione "DontDestroyOnLoad", nella vista gerarchica.
Usando la PlayerPrefs
classe
Unity ha una classe integrata per gestire i dati persistenti di base chiamatiPlayerPrefs
. Tutti i dati impegnati nel PlayerPrefs
file persisteranno per tutte le sessioni di gioco , quindi, naturalmente, è in grado di conservare i dati attraverso le scene.
Il PlayerPrefs
file può memorizzare le variabili di tipo string
, int
e float
. Quando inseriamo valori nel PlayerPrefs
file, ne forniamo un ulteriore string
come chiave. Usiamo la stessa chiave per recuperare in seguito i nostri valori dal PlayerPref
file.
using UnityEngine;
/// <summary>Manages data for persistance between play sessions.</summary>
public class SaveManager : MonoBehaviour
{
/// <summary>The player's name.</summary>
public string playerName = "";
/// <summary>The player's score.</summary>
public int playerScore = 0;
/// <summary>The player's health value.</summary>
public float playerHealth = 0f;
/// <summary>Static record of the key for saving and loading playerName.</summary>
private static string playerNameKey = "PLAYER_NAME";
/// <summary>Static record of the key for saving and loading playerScore.</summary>
private static string playerScoreKey = "PLAYER_SCORE";
/// <summary>Static record of the key for saving and loading playerHealth.</summary>
private static string playerHealthKey = "PLAYER_HEALTH";
/// <summary>Saves playerName, playerScore and
/// playerHealth to the PlayerPrefs file.</summary>
public void Save()
{
// Set the values to the PlayerPrefs file using their corresponding keys.
PlayerPrefs.SetString(playerNameKey, playerName);
PlayerPrefs.SetInt(playerScoreKey, playerScore);
PlayerPrefs.SetFloat(playerHealthKey, playerHealth);
// Manually save the PlayerPrefs file to disk, in case we experience a crash
PlayerPrefs.Save();
}
/// <summary>Saves playerName, playerScore and playerHealth
// from the PlayerPrefs file.</summary>
public void Load()
{
// If the PlayerPrefs file currently has a value registered to the playerNameKey,
if (PlayerPrefs.HasKey(playerNameKey))
{
// load playerName from the PlayerPrefs file.
playerName = PlayerPrefs.GetString(playerNameKey);
}
// If the PlayerPrefs file currently has a value registered to the playerScoreKey,
if (PlayerPrefs.HasKey(playerScoreKey))
{
// load playerScore from the PlayerPrefs file.
playerScore = PlayerPrefs.GetInt(playerScoreKey);
}
// If the PlayerPrefs file currently has a value registered to the playerHealthKey,
if (PlayerPrefs.HasKey(playerHealthKey))
{
// load playerHealth from the PlayerPrefs file.
playerHealth = PlayerPrefs.GetFloat(playerHealthKey);
}
}
/// <summary>Deletes all values from the PlayerPrefs file.</summary>
public void Delete()
{
// Delete all values from the PlayerPrefs file.
PlayerPrefs.DeleteAll();
}
}
Si noti che prendo ulteriori precauzioni durante la gestione del PlayerPrefs
file:
- Ho salvato ciascuna chiave come a
private static string
. Questo mi permette di garantire che sto sempre usando la chiave giusta e significa che se devo cambiare la chiave per qualsiasi motivo, non ho bisogno di assicurarmi di cambiare tutti i riferimenti ad essa.
- Salvo il
PlayerPrefs
file sul disco dopo averlo scritto. Questo probabilmente non farà differenza, se non si implementa la persistenza dei dati nelle sessioni di gioco. PlayerPrefs
si salva sul disco nel corso di una normale applicazione stretta, ma non può naturalmente chiamare se il gioco si blocca.
- Veramente controllo che ogni chiave esista in
PlayerPrefs
, prima di tentare di recuperare un valore ad essa associato. Questo potrebbe sembrare inutile doppio controllo, ma è una buona pratica avere.
- Ho un
Delete
metodo che cancella immediatamente il PlayerPrefs
file. Se non si intende includere la persistenza dei dati nelle sessioni di gioco, è possibile prendere in considerazione la possibilità di attivare questo metodo Awake
. Deselezionando la PlayerPrefs
lima all'inizio di ogni partita, ci si assicura che tutti i dati che ha persistono dalla sessione precedente non viene erroneamente trattati come dati dalla corrente sessione.
Puoi vedere PlayerPrefs
in azione, sotto. Nota che quando faccio clic su "Salva dati", chiamo direttamente il Save
metodo e quando faccio clic su "Carica dati", chiamo direttamente il Load
metodo. La tua implementazione probabilmente varierà, ma dimostra le basi.
Come nota finale, dovrei sottolineare che è possibile espandere su base PlayerPrefs
, per memorizzare tipi più utili. JPTheK9 fornisce una buona risposta a una domanda simile , in cui forniscono uno script per la serializzazione di array in forma di stringa, da archiviare in un PlayerPrefs
file. Ci indicano anche il Wiki della community di Unify , in cui un utente ha caricato uno PlayerPrefsX
script più ampio per consentire il supporto di una varietà più ampia di tipi, come vettori e array.