using JetBrains.Annotations; using UnityEngine; public abstract class Singleton : Singleton where T : MonoBehaviour { #region Fields [CanBeNull] protected static T _instance; [NotNull] // ReSharper disable once StaticMemberInGenericType private static readonly object Lock = new object(); [SerializeField] protected bool _persistent = false; #endregion #region Properties [NotNull] public static T Inst { get { if (Quitting) { if (_instance != null) return _instance; var instances = FindObjectsOfType(); 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."); // ReSharper disable once AssignNullToNotNullAttribute return null; } lock (Lock) { if (_instance != null) return _instance; var instances = FindObjectsOfType(); 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) { DontDestroyOnLoad(gameObject); } else if (_instance != this) { Destroy(_instance.gameObject); DontDestroyOnLoad(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 } // public class Singleton : MonoBehaviour where T : MonoBehaviour // { // protected static GameObject _gameObject; // protected static T _instance = null; // // [SerializeField] // protected bool _persistent = false; // // public static T Inst // { // get // { // if (null != _instance) // { // return _instance; // } // // _instance = (T)FindAnyObjectByType(typeof(T)); // // if (_instance == null) // { // _gameObject = new GameObject(typeof(T).Name); // _instance = _gameObject.AddComponent(); // } // // return _instance; // } // } // }