Menu
CoddyTech

Generyczny singleton

Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 43 z 64.

Singleton z sekcji 3 to pięć wierszy, które powtarza każdy menedżer: statyczne Instance, Awake, które je ustawia, oraz sprawdzanie duplikatów. Ogólna klasa bazowa zapisuje je raz. Każdy menedżer po niej dziedziczy i podaje swoją nazwę jako typ:

public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    protected virtual void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }
        Instance = this as T;
    }
}

public class ScoreManager : Singleton<ScoreManager>
{
    public int score;
    public void Add(int points) { score += points; }
}

public class SoundManager : Singleton<SoundManager>
{
    public void Play(string clip) { Debug.Log("Playing " + clip); }
}
// w dowolnym skrypcie
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");

Statyczny element członkowski klasy generycznej należy do każdego utworzonego na jej podstawie typu: Singleton<ScoreManager> i Singleton<SoundManager> to dwa typy, z których każdy ma własne Instance, więc menedżery nigdy go nie współdzielą. ScoreManager.Instance ma już typ ScoreManager — właśnie do tego służy T. W klasie bazowej this jest znane tylko jako Singleton<T>, więc this as T przekazuje je jako typ menedżera, którym faktycznie jest.

Klasa bazowa jest abstrakcyjna: Unity umieszcza na obiektach tylko menedżery. Menedżer, który potrzebuje własnego Awake, nie może napisać zwykłego void Awake(). Ta metoda zasłania metodę klasy bazowej (kompilator wyświetli ostrzeżenie), Unity wywołuje tylko metodę menedżera, a Instance nigdy nie zostaje ustawione. Zastąp ją i najpierw wywołaj metodę klasy bazowej:

protected override void Awake()
{
    base.Awake();
    score = 0;
}
challenge icon

Wyzwanie

Średni

Zapewnij obu menedżerom bazę, która przetrwa wczytywanie scen.

  1. W PersistentSingleton napisz protected virtual void Awake(): pierwszy staje się Instance i pozostaje aktywny (DontDestroyOnLoad); kolejny niszczy sam siebie.
  2. Wallet i MusicPlayer dziedziczą po tej klasie; usuń ich Instance oraz Awake klasy Wallet.
  3. MusicPlayer przesłania Awake: base.Awake(), a następnie, jeśli jest instancją, wyświetla w logu Now playing: Adventure.

Naciśnij „Graj”, odwiedź las i wróć: 1 moneta. Następnie naciśnij „Sprawdź”.

Spróbuj swoich sił

using UnityEngine;

public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
    public static T Instance { get; private set; }

    // Awake: zachowaj pierwszy obiekt podczas wczytywania kolejnych scen, a każdy następny zniszcz
}

Wszystkie lekcje w sekcji Architektura gier w Unity

Poćwicz samodzielnie: Edytor online Unity