Rozwijam swoją pierwszą grę 2D w Unity i natknąłem się na to, co wydaje się ważnym pytaniem.
Jak obsługiwać dane między scenami?
Wydaje się, że istnieją różne odpowiedzi na to:
Ktoś wspomniał o użyciu PlayerPrefs , podczas gdy inni powiedzieli mi, że należy to wykorzystać do przechowywania innych rzeczy, takich jak jasność ekranu i tak dalej.
Ktoś powiedział mi, że najlepszym sposobem jest zapisanie wszystkiego w zapisanej grze za każdym razem, gdy zmieniam sceny, i upewnienie się, że kiedy nowa scena się załaduje, ponownie uzyskam informacje z zapisanej gry. Wydawało mi się to marnotrawstwem w wydajności. Czy się myliłem?
Drugim rozwiązaniem, które wdrożyłem do tej pory, jest posiadanie globalnego obiektu gry, który nie jest niszczony między scenami, obsługując wszystkie dane między scenami. Kiedy więc gra się rozpoczyna, ładuję scenę początkową, w której ten obiekt jest ładowany. Po zakończeniu wczytuje pierwszą prawdziwą scenę gry, zwykle menu główne.
To jest moja realizacja:
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class GameController : MonoBehaviour {
// Make global
public static GameController Instance {
get;
set;
}
void Awake () {
DontDestroyOnLoad (transform.gameObject);
Instance = this;
}
void Start() {
//Load first game scene (probably main menu)
Application.LoadLevel(2);
}
// Data persisted between scenes
public int exp = 0;
public int armor = 0;
public int weapon = 0;
//...
}
Ten obiekt może być obsługiwany w moich innych klasach w następujący sposób:
private GameController gameController = GameController.Instance;
Chociaż to działało do tej pory, przedstawia mi jeden duży problem: jeśli chcę załadować scenę bezpośrednio, powiedzmy na przykład, ostateczny poziom gry, nie mogę załadować jej bezpośrednio, ponieważ ta scena nie zawiera tego globalny obiekt gry .
Czy radzę sobie z tym problemem w niewłaściwy sposób? Czy istnieją lepsze praktyki dla tego rodzaju wyzwań? Bardzo chciałbym usłyszeć wasze opinie, przemyślenia i sugestie na ten temat.
Dzięki
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.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
klasyUnity ma wbudowaną klasę do zarządzania podstawowymi trwałymi danymi o nazwie
PlayerPrefs
. Wszelkie dane przypisane doPlayerPrefs
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ówstring
,int
afloat
. Kiedy wstawiamy wartości doPlayerPrefs
pliku, dostarczamy dodatkowystring
jako klucz. Używamy tego samego klucza, aby później pobrać nasze wartości zPlayerPref
pliku.Pamiętaj, że podczas obsługi
PlayerPrefs
pliku podejmuję dodatkowe środki ostrożności :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.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.PlayerPrefs
, zanim spróbuję pobrać wartość z nim powiązaną. Może się to wydawać bezcelowym podwójnym sprawdzaniem, ale warto to zrobić.Delete
metodę, która natychmiast czyściPlayerPrefs
plik. Jeśli nie zamierzasz uwzględniać trwałości danych w sesjach odtwarzania, możesz rozważyć włączenie tej metodyAwake
. Przez wyczyszczeniePlayerPrefs
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 wPlayerPrefs
pliku. Wskazują nas także na Wiki społeczności Unify , gdzie użytkownik przesłał bardziej rozbudowanyPlayerPrefsX
skrypt, aby umożliwić obsługę większej liczby typów, takich jak wektory i tablice.źródło