Introdução
Há um grande número de padrões e antipadrões de programação. Muitas vezes, o uso de padrões nos dita a experiência e o conhecimento real de si mesmos. Neste artigo, quero discutir com você a aplicação do padrão Singleton , ou seja, sua implementação na Net, aplicada ao Unity.
Singleton
Observo que estou escrevendo código em uma equipe, por isso trabalho o máximo possível dentro do código para descarregar a equipe e eliminar a necessidade de pensar em algumas das dificuldades de implementar certos padrões no Unity.
Estudando a literatura na Rede 1 , em relação a esta questão 2, e como resultado do trabalho em vários projetos, nasceu a seguinte turma:
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
    private static T instance = null;
    private bool alive = true;
    public static T Instance
    {
        get
        {
            if (instance != null)
            {
                return instance;
            }
            else
            {
                
                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 Singleton! Check project.");
                            for (int i = 0; i < managers.Length; ++i)
                            {
                                T manager = managers[i];
                                Destroy(manager.gameObject);
                            }
                        }
                    }
                }
                
                GameObject go = new GameObject(typeof(T).Name, typeof(T));
                instance = go.GetComponent<T>();
        instance.Initialization();
                DontDestroyOnLoad(instance.gameObject);
                return instance;
            }
        }
        
        set
        {
            instance = value as T;
        }
    }
    
    
    
    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 Singleton! Check project.");
            DestroyImmediate(this);
        }
    }
    protected void OnDestroy() { alive = false; }
    protected void OnApplicationQuit() { alive = false; }
    protected virtual void Initialization() { }
}
Vou me concentrar em vários aspectos.
Criação de Objetos
Ao expandir um projeto, e especialmente o trabalho em equipe> 3 pessoas, geralmente surge uma situação quando a sequência de criação de objetos se torna pouco clara. Estritamente falando 3 , a sequência de chamadas para Awake () é aleatória ( é claro, isso não é totalmente verdade e o processo pode ser influenciado, mas a documentação é sagrada), e é por isso que é necessário eliminar essa desvantagem irritante implementando a propriedade Instance {get;} . Como resultado, obtemos acesso total ao singleton de Awake () de outras classes.
, Lazy, Awake() .
4-4, , Instance{get;}.
Unity — Awake(). , , Initialization(). (KISS).
, DI SD. . .
, , OnDestroy(), OnApplicationQuit() 5:
Did you spawn new GameObjects from OnDestroy?
, , , . , IsAlive(), , . , ...
Cada vez mais, chego à conclusão de que, usando o paradigma Unity, é possível implementar meus projetos sem Singleton. Geralmente, a aplicação desse padrão torna seu código altamente conectado e extremamente frágil.
Obrigado.
Fontes
- Richter J. "CLR via C #. Programação no Microsoft.NET # Framework 4.5 in C #", 2013
- https://www.codingame.com/playgrounds/1979/different-ways-to-implement-singleton-in--net-and-make-people-hate-you-along-the-way
- https://docs.unity3d.com/en/current/ScriptReference/MonoBehaviour.Awake.html
- https://ru.wikipedia.org/wiki/Design_Patterns
- Dickinson Chris "Otimização de jogos Unity 2017, segunda edição", 2017