Idealnym sposobem przechowywania zmiennych między scenami jest wykorzystanie klasy menedżera singletonów. Tworząc klasę do przechowywania trwałych danych i ustawiając tę klasę na DoNotDestroyOnLoad(), możesz zapewnić, że będzie ona natychmiast dostępna i będzie się utrzymywać między scenami.
Inną opcją jest użycie PlayerPrefsklasy. PlayerPrefsjest przeznaczony do zapisywania danych między sesjami odtwarzania , ale nadal będzie służył do zapisywania danych między scenami .
Korzystanie z zajęć singleton i DoNotDestroyOnLoad()
Poniższy skrypt tworzy trwałą klasę singleton. Klasa singleton jest klasą zaprojektowaną do uruchamiania tylko jednej instancji w tym samym czasie. Zapewniając taką funkcjonalność, możemy bezpiecznie stworzyć statyczne odniesienie, aby uzyskać dostęp do klasy z dowolnego miejsca. Oznacza to, że możesz bezpośrednio uzyskać dostęp do klasy DataManager.instance, w tym dowolne zmienne publiczne w klasie.
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);
}
}
Poniżej możesz zobaczyć singletona w akcji. Zauważ, że jak tylko uruchomię scenę początkową, obiekt DataManager przechodzi od nagłówka specyficznego dla sceny do nagłówka „DontDestroyOnLoad” w widoku hierarchii.

Korzystanie z PlayerPrefsklasy
Unity ma wbudowaną klasę do zarządzania podstawowymi trwałymi danymi o nazwiePlayerPrefs . Wszelkie dane przypisane do PlayerPrefspliku będą się utrzymywać podczas sesji gry , więc oczywiście jest w stanie utrwalać dane między scenami.
PlayerPrefsPlik można zapisać zmienne typów string, inta float. Kiedy wstawiamy wartości do PlayerPrefspliku, dostarczamy dodatkowy stringjako klucz. Używamy tego samego klucza, aby później pobrać nasze wartości z PlayerPrefpliku.
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();
}
}
Pamiętaj, że podczas obsługi PlayerPrefspliku podejmuję dodatkowe środki ostrożności :
- Zapisałem każdy klucz jako
private static string. To pozwala mi zagwarantować, że zawsze używam właściwego klucza, a to oznacza, że jeśli muszę zmienić klucz z jakiegokolwiek powodu, nie muszę się upewnić, że zmienię wszystkie odniesienia do niego.
- Zapisuję
PlayerPrefsplik na dysku po zapisaniu na nim. Prawdopodobnie nie zrobi to różnicy, jeśli nie zaimplementujesz utrwalania danych w sesjach odtwarzania. PlayerPrefs będzie zapisać na dysku w trakcie normalnego zamknięcia aplikacji, ale to nie może naturalnie zadzwonić jeśli gra wywala.
- Rzeczywiście sprawdzam , czy każdy klucz istnieje w
PlayerPrefs, zanim spróbuję pobrać wartość z nim powiązaną. Może się to wydawać bezcelowym podwójnym sprawdzaniem, ale warto to zrobić.
- Mam
Deletemetodę, która natychmiast czyści PlayerPrefsplik. Jeśli nie zamierzasz uwzględniać trwałości danych w sesjach odtwarzania, możesz rozważyć włączenie tej metody Awake. Przez wyczyszczenie PlayerPrefspliku na początku każdej gry, upewnij się, że wszelkie dane, które nie utrzymują się od poprzedniej sesji nie jest błędnie traktowane jako dane z bieżącej sesji.
Możesz zobaczyć PlayerPrefsw akcji poniżej. Zauważ, że kiedy klikam „Zapisz dane”, bezpośrednio wywołuję Savemetodę, a kiedy klikam „Ładuj dane”, bezpośrednio wywołuję Loadmetodę. Twoja implementacja prawdopodobnie będzie się różnić, ale pokazuje podstawy.

Na koniec chciałbym zauważyć, że możesz rozwinąć podstawowe PlayerPrefs, aby przechowywać bardziej przydatne typy. JPTheK9 zapewnia dobrą odpowiedź na podobne pytanie , w którym zapewniają skrypt do szeregowania tablic w postaci ciągów, które mają być przechowywane w PlayerPrefspliku. Wskazują nas także na Wiki społeczności Unify , gdzie użytkownik przesłał bardziej rozbudowany PlayerPrefsXskrypt, aby umożliwić obsługę większej liczby typów, takich jak wektory i tablice.