Обобщённый синглтон
Часть раздела Архитектура игр в Unity путешествия по Unity на Coddy. Урок 43 из 64.
Синглтон из раздела 3 — это пять строк, которые повторяет каждый менеджер: статический Instance, Awake, который задаёт его, и проверка на дубликат. Обобщённый базовый класс записывает их один раз. Каждый менеджер наследуется от него, указывая своё имя в качестве типа:
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); }
}// в любом скрипте
ScoreManager.Instance.Add(10);
SoundManager.Instance.Play("coin");Статический член обобщённого класса принадлежит каждому созданному на его основе типу: Singleton<ScoreManager> и Singleton<SoundManager> — это два типа, у каждого из которых есть собственный Instance, поэтому менеджеры никогда не используют один общий. ScoreManager.Instance уже имеет тип ScoreManager — именно для этого нужен T. Внутри базового класса this известен только как Singleton<T>, поэтому this as T передаёт его как тот тип менеджера, которым он на самом деле является.
Базовый класс абстрактный: Unity размещает на объектах только менеджеры. Если менеджеру нужен собственный Awake, нельзя объявлять обычный void Awake(). Этот метод скроет метод базового класса (компилятор предупредит об этом), Unity вызовет только метод менеджера, и Instance так и не будет задан. Переопределите метод и сначала вызовите базовый:
protected override void Awake()
{
base.Awake();
score = 0;
}Задание
СреднеСоздай для обоих менеджеров базовый класс, который сохраняется при загрузке сцен.
- В
PersistentSingletonнапишиprotected virtual void Awake(): первый экземпляр становитсяInstanceи сохраняется (DontDestroyOnLoad); следующий уничтожает сам себя. WalletиMusicPlayerнаследуются от него; удали ихInstanceи Awake из Wallet.- В
MusicPlayerпереопредели Awake:base.Awake(), затем, если он является Instance, выведи в журналNow playing: Adventure.
Нажми «Играть», сходи в лес и вернись: 1 монета. Затем нажми «Проверить».
Попробуйте сами
using UnityEngine;
public abstract class PersistentSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
public static T Instance { get; private set; }
// Awake: сохранять первый экземпляр при загрузке сцен, а все последующие уничтожать
}
Все уроки раздела Архитектура игр в Unity
1Компоненты, а не иерархии
Небольшие компонентыБазовый скрипт врагаАбстрактные компонентыКомпоненты работают вместеПовторение: модульная турельПовторение: спаренная пушка4Сериализованные данные
Сериализуемые классыСписки в инспектореПеречисления в инспектореПовторение: таблица добычиПовторение: определяем добычу2Интерфейсы в Unity
IDamageableИнтерфейсы и TryGetComponentGetComponentsПовторение: клавиша взаимодействияПовторение: ближайший в пределах досягаемости5ScriptableObjects
Ресурсы данныхХарактеристики оружияОбщие настройкиСохраняем ветерВолны как данныеПовторение: база предметовПовторение: покупка в магазине8Переиспользуемый код
Методы расширенияОбобщённый синглтонОбобщённые вспомогательные методыПовторение: FindNearestПотренируйтесь самостоятельно: Песочница Unity