// using UnityEngine; // // [DefaultExecutionOrder(-1)] // public abstract class Singleton : MonoBehaviour where T : MonoBehaviour // { // [SerializeField] // private bool _persistent; // // private static T _instance; // public static T Instance // { // get // { // if (_instance) return _instance; // // _instance = FindAnyObjectByType(FindObjectsInactive.Include); // // if (_instance) return _instance; // // var obj = new GameObject // { // name = typeof(T).Name // }; // _instance = obj.AddComponent(); // // return _instance; // } // } // // private void Awake() // { // if (!_instance) // { // _instance = this as T; // // if (_persistent) // { // DontDestroyOnLoad(gameObject); // } // // OnAwake(); // } // else if (_instance != this) // { // Destroy(gameObject); // } // } // // protected virtual void OnAwake() {} // } using JetBrains.Annotations; using UnityEngine; [DefaultExecutionOrder(-1)] public abstract class Singleton : Singleton where T : MonoBehaviour { #region Fields [CanBeNull] private static T _instance; [NotNull] private static readonly object _lock = new(); [SerializeField] private bool _persistent; #endregion #region Properties [NotNull] public static T Instance { get { if (Quitting) { if (_instance != null) return _instance; var instances = FindObjectsByType(FindObjectsSortMode.None); var count = instances.Length; if (count > 0) { if (count == 1) return _instance = instances[0]; //Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] There should never be more than one {nameof(Singleton)} of type {typeof(T)} in the scene, but {count} were found. The first instance found will be used, and all others will be destroyed."); for (var i = 1; i < instances.Length; i++) Destroy(instances[i]); return _instance = instances[0]; } //Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] Instance will not be returned because the application is quitting."); return null; } lock (_lock) { if (_instance != null) return _instance; var instances = FindObjectsByType(FindObjectsSortMode.None); var count = instances.Length; if (count > 0) { if (count == 1) return _instance = instances[0]; Debug.LogWarning($"[{nameof(Singleton)}<{typeof(T)}>] There should never be more than one {nameof(Singleton)} of type {typeof(T)} in the scene, but {count} were found. The first instance found will be used, and all others will be destroyed."); for (var i = 1; i < instances.Length; i++) Destroy(instances[i]); return _instance = instances[0]; } Debug.Log($"[{nameof(Singleton)}<{typeof(T)}>] An instance is needed in the scene and no existing instances were found, so a new instance will be created."); return _instance = new GameObject($"({nameof(Singleton)}){typeof(T)}") .AddComponent(); } } } #endregion #region Methods protected virtual void Awake() { if (_persistent) { if (_instance == null) { _instance = this as T; DontDestroyOnLoad(gameObject); } else if (_instance != this) { Destroy(gameObject); } } OnAwake(); } protected virtual void OnAwake() { } #endregion } public abstract class Singleton : MonoBehaviour { #region Properties public static bool Quitting { get; private set; } #endregion #region Methods protected virtual void OnApplicationQuit() { Quitting = true; } #endregion }