Menu
CoddyTech

Zachowaj między scenami

Część sekcji Tworzenie prawdziwych gier ścieżki Unity w Coddy. Lekcja 20 z 56.

Wczytanie sceny niszczy wszystkie obiekty z poprzedniej sceny, ale niektóre rzeczy muszą przetrwać całą grę, na przykład monety, które gracz zbiera na kolejnych poziomach. DontDestroyOnLoad(gameObject) przenosi obiekt poza jego scenę, do osobnej sceny o nazwie DontDestroyOnLoad, widocznej w Hierarchy podczas gry, której wczytywanie nie narusza. Działa tylko na obiekcie głównym: w przypadku obiektu podrzędnego Unity wyświetla ostrzeżenie i niczego nie zachowuje. Obiekty podrzędne zachowanego obiektu również zostają zachowane, ale obiekty, do których tylko wskazuje, już nie: po wczytaniu pole wskazujące na obiekt ze starej sceny przechowuje zniszczony obiekt, który jest równy null.

public class GameSession : MonoBehaviour
{
    public static GameSession Instance;
    public int coins;

    void Awake()
    {
        if (Instance != null)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
}

Ten GameSession znajduje się w scenie Menu. Gra przechodzi z Menu do Level1, a następnie wraca do Menu, które ponownie tworzy wszystkie swoje obiekty, w tym nowy GameSession, podczas gdy zachowany obiekt nadal istnieje. Bez sprawdzenia w Awake istniałyby dwa obiekty, a nowy przejąłby Instance z 0 monetami. Dzięki temu sprawdzeniu nowy obiekt wykrywa, że Instance jest już ustawione, niszczy siebie i kończy działanie, a sesja, która przetrwała kolejne poziomy, pozostaje.

return ma znaczenie, ponieważ Destroy czeka do końca klatki. Bez niego reszta Awake nadal wykonałaby się dla nowego obiektu: Instance = this; wskazywałoby wszystkie skrypty na obiekt, który za chwilę zostanie zniszczony.

challenge icon

Wyzwanie

Łatwy

Zegar speedrunu. Obiekt RunClock w Level1 zlicza sekundy całego biegu i zapisuje międzyczas za każdym razem, gdy poziom zostaje ukończony. Złoty Goal w Level1 wczytuje Level2, którego cel ponownie wczytuje Level1, a każdy cel najpierw wywołuje RunClock.Instance.Split(). Każdy poziom ma własny HUD z elementem ClockText; w Inspectorze przypisano do RunClock ten z Level1. Strzałkami poruszasz Playerem. Zmień RunClock.cs, tak aby:

  • zegar działał nadal przy każdym wczytaniu sceny, bez ponownego uruchamiania;
  • czas był zawsze wyświetlany w elemencie ClockText aktualnie otwartego poziomu, jako Time: 12.3;
  • powrót do Level1, który ma własny RunClock, nadal pozostawiał jeden zegar — ten, który już działał — i aby RunClock.Instance wskazywało właśnie na niego.

Naciśnij Play, przejdź do Level2 i wróć, a następnie ponownie ukończ Level1 i naciśnij Check.

Spróbuj swoich sił

using UnityEngine;
using TMPro;

public class RunClock : MonoBehaviour
{
    public static RunClock Instance;
    public TMP_Text clockText;
    private float seconds;

    void Awake()
    {
        Instance = this;
    }

    void Update()
    {
        seconds += Time.deltaTime;
        clockText.text = "Time: " + seconds.ToString("0.0");
    }

    public void Split()
    {
        Debug.Log("Split: " + seconds.ToString("0.0"));
    }
}
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Tworzenie prawdziwych gier