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 PlayerPrefs
klasy. PlayerPrefs
jest 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 PlayerPrefs
klasy
Unity ma wbudowaną klasę do zarządzania podstawowymi trwałymi danymi o nazwiePlayerPrefs
. Wszelkie dane przypisane do PlayerPrefs
pliku będą się utrzymywać podczas sesji gry , więc oczywiście jest w stanie utrwalać dane między scenami.
PlayerPrefs
Plik można zapisać zmienne typów string
, int
a float
. Kiedy wstawiamy wartości do PlayerPrefs
pliku, dostarczamy dodatkowy string
jako klucz. Używamy tego samego klucza, aby później pobrać nasze wartości z PlayerPref
pliku.
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 PlayerPrefs
pliku 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ę
PlayerPrefs
plik 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
Delete
metodę, która natychmiast czyści PlayerPrefs
plik. Jeśli nie zamierzasz uwzględniać trwałości danych w sesjach odtwarzania, możesz rozważyć włączenie tej metody Awake
. Przez wyczyszczenie PlayerPrefs
pliku 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ć PlayerPrefs
w akcji poniżej. Zauważ, że kiedy klikam „Zapisz dane”, bezpośrednio wywołuję Save
metodę, a kiedy klikam „Ładuj dane”, bezpośrednio wywołuję Load
metodę. 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 PlayerPrefs
pliku. Wskazują nas także na Wiki społeczności Unify , gdzie użytkownik przesłał bardziej rozbudowany PlayerPrefsX
skrypt, aby umożliwić obsługę większej liczby typów, takich jak wektory i tablice.