Как стать автором
Обновить

Комментарии 15

Почти DI :)

Лучше в Dictionary ключи не string, а тип (T). При таком подходе поиск зависимостей по проекту делать проще, чем по стрингам.
Хорошая мысль, которая не пришла мне в голову, потому что слишком просто и без трудностей) Спасибо!
Как бы это помягче сказать, чтобы не показаться грубым… Это велосипед, причём плохой.
По факту это Service Locator, который уже давно считается антипаттерном, к тому же очень скудно реализованный (например, что мешает в качестве ключа использовать тип?). Плюс синглтоны, что тоже весьма печально.
Курите StrangeIoc/Zenject, как гораздо более вменяемую альтернативу.
Какие альтернативы синглтона в unity вы можете подсказать?
вам же подсказали — Zenject. Strange крайне не рекомендую. Слишком свою архитектуру навязывают. Живем с ним на двух проектах как с наследием, дико плюемся (имеется опыт проекта с Зенджектом)
Полностью избавиться от синглтонов в Unity действительно весьма сложно и даже не всегда оправданно. Но если инъекция зависимостей поможет распутать код, то почему бы и да.
Главное Zenject не берите.
ага, лучше StrangeIOC, чтобы пораньше проект закрыть )
Поддерживаю
Сам синглтон еще терпим — но в крайне редких случаях. Unity позволяет обойтись без него стандартными средствами. Проблем приносит на порядок больше.

SL — просто отличный пример как не стоит делать (за редким исключением).

По факту SL хорошо смотрится вкупе с DI — когда каждый сервис является подмножеством взаимозаменяемых сервисов, но сложность этого подхода все же ставит его в антипаттерны.
Ну, DI обычно воспринимается как преемник SL, вытесняющий его полностью.
Я сильно ориентируюсь по этой статье www.skipy.ru/architecture/module_design.html

Применительно к Unity — совсем немного времени на нем провел, пришел из плюсов с полгодика назад.

Отсюда вопрос — хорошая литература и проекты по Unity (Net)- не подскажешь? А то я больше занимаюсь обработкой изображений, на Unity у меня небольшой проектик по AR (в ТЦ Капитолий стоит, майки примерять) и чувствую что нагреб граблей по незнанию.
Хорошей литературы (вот чтоб прямо книги) по Unity я не видел. Искал где-то года два назад, может сейчас что-нибудь да поменялось. Что-то толковое может быть по отдельным кускам, типа Shader Graph, но я не слежу.
С другой стороны, если интересен их перспективный стек DOTS, есть отличное чтиво R.Fabian «Data-Oriented Design», но он не про конкретно технологию, а про сам подход. Даже официальная бесплатная онлайн-версия есть.
Спасибо!
Проверяли логику работы данных синглтонов при переходе между сценами?

Накидаю кейс проверки — нужно вызывать методы синглтона посредством делегатов (UnityEvent). Допустим используем синглтон для музыки, пишем обертку для дизайнера, чтобы он мог ручками накидывать необходимые ему взаимосвязи через интерфейс Unity Editor — как отработает ваш код?

Я пока данный глюк так и не поборол.

Под катом мой код сингелтона:

Singelton.cs
using UnityEngine;

/// <summary>
/// Реализация сингелтона для наследования.
/// </summary>
/// <typeparam name="T">Класс, который нужно сделать сингелтоном</typeparam>
/// <remarks>/// Если необходимо обращаться к классу во время OnDestroy или OnApplicationQuit
/// необходимо проверять наличие объекта через IsAlive. Объект может быть уже 
/// уничтожен, и обращение к нему вызовет его еще раз.
/// 
/// 
/// При использовании в дочернем классе Awake, OnDestroy, 
/// OnApplicationQuit необходимо вызывать базовые методы
/// base.Awake() и тд.
/// 
/// Добавил скрываемый метод Initialization - чтобы перегружать его и использовать 
/// необходимые действия.
/// 
/// Создание объекта производится через unity, поэтому использовать блокировку 
/// объекта нет необходимости. Однако ее можно добавить, в случае если 
/// понадобится обращение к объекту из других потоков.
/// 
/// Из книг:
///     - Рихтер "CLR via C#"
///     - Chris Dickinson "Unity 2017 Game optimization"
///</remarks>

public class Singelton<T> : MonoBehaviour where T : Singelton<T>
{

    private static T instance = null;

    private bool alive = true;

    public static T Instance
    {
        get
        {
            if (instance != null)
            {
                return instance;
            }
            else
            {
                //Find T
                T[] managers = GameObject.FindObjectsOfType<T>();
                if (managers != null)
                {
                    if (managers.Length == 1)
                    {
                        instance = managers[0];
                        DontDestroyOnLoad(instance);
                        return instance;
                    }
                    else
                    {
                        if (managers.Length > 1)
                        {
                            Debug.LogError($"Have more that one {typeof(T).Name} in scene. " +
                                            "But this is Singelton! Check project.");
                            for (int i = 0; i < managers.Length; ++i)
                            {
                                T manager = managers[i];
                                Destroy(manager.gameObject);
                            }
                        }
                    }
                }
                //create 
                GameObject go = new GameObject(typeof(T).Name, typeof(T));
                instance = go.GetComponent<T>();
				instance.Initialization();
                DontDestroyOnLoad(instance.gameObject);
                return instance;
            }
        }

        //Can be initialized externally
        set
        {
            instance = value as T;
        }
    }

    /// <summary>
    /// Check flag if need work from OnDestroy or OnApplicationExit
    /// </summary>
    public static bool IsAlive
    {
        get
        {
            if (instance == null)
                return false;
            return instance.alive;
        }
    }


	protected void Awake()
	{
		if (instance == null)
		{
			DontDestroyOnLoad(gameObject);
			instance = this as T;
			Initialization();
		}
		else
		{
			Debug.LogError($"Have more that one {typeof(T).Name} in scene. " +
							"But this is Singelton! Check project.");
		    DestroyImmediate(this);
		}
	}

    protected void OnDestroy() { alive = false; }

    protected void OnApplicationQuit() { alive = false; }

	protected virtual void Initialization() { }
}

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации