public abstract class MonoSingleton<T> : MonoBehaviour where T : Component
    {
        private static object _lock = new object();
        private static bool _shuttingDown = false;
        private static T _instance;

        public static T Instance
        {
            get
            {
                if(_shuttingDown)
                {
                    Debug.Log($"[Singleton] Instance '{typeof(T)} already destroyed. returning null'");

                    return null;
                }

                lock(_lock)
                {
                    if(_instance == null)
                    {
                        _instance = (T)FindObjectOfType(typeof(T));

                        if(_instance == null)
                        {
                            GameObject newGameObject = new GameObject(typeof(T).Name, typeof(T));

                            _instance = newGameObject.GetComponent<T>();
                        }
                    }
                }
                return _instance;  
            }
        }

        protected virtual void Awake()
        {
            lock(_lock)
            {
                var objects = FindObjectsOfType(GetType());

                if(objects.Length > 1 && _instance != null && _instance != this)
                {
                    Destroy(this.gameObject);

                    return;
                }

                SetDontDestroy(this.transform);
            }
        }

        private static void SetDontDestroy(Transform transform)
        {
            if(Application.isPlaying == true)
            {
                DontDestroyOnLoad(transform.root.gameObject);
            }
            else
            {
                DontDestroyOnLoad(transform.gameObject);
            }
        }

        private void OnApplicationQuit()
        {
            if(_instance)
            {
                _shuttingDown = true;
            }
        }

        private void OnDestroy()
        {
            if(_instance && _instance == this)
            {
                _shuttingDown = true;
            }
        }
    }