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 Awake() { if (_persistent) { if (_instance == null) { _instance = this as T; // 명시적 타입 변환 DontDestroyOnLoad(gameObject); // 씬 전환 시 파괴되지 않도록 설정 } else if (_instance != this) { Destroy(gameObject); // 현재 인스턴스가 _instance와 다르면 현재 오브젝트를 파괴 } } 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; // } // } // }