using UnityEngine; namespace IPA.Utilities { /// /// Generate a persistent singleton which can be destroyed. /// /// public class ModSingleton : MonoBehaviour where T : MonoBehaviour { /// /// The stored reference for the instance /// protected static T _instance; /// /// The lock for the instance to prevent more than one being created. /// protected static object _lock = new object(); /// /// Checks to see if the singleton if the singleton can be accessed /// public static bool IsSingletonAvailable => _instance != null; /// /// Noncapitalized version which points to the actual property. /// public static T instance => Instance; /// /// Creates and or returns the singleton /// public static T Instance { get { T result; object @lock = _lock; lock (@lock) { if (_instance == null) { _instance = (T)((object)FindObjectOfType(typeof(T))); if (FindObjectsOfType(typeof(T)).Length > 1) { IPA.Logging.Logger.log.Warn($"[Singleton] Something went really wrong - there should never be more than one singleton of {nameof(T)}"); return _instance; } if (_instance == null) { GameObject gameObject = new GameObject(); _instance = gameObject.AddComponent(); gameObject.name = $"{nameof(T)} Singleton"; DontDestroyOnLoad(gameObject); } } result = _instance; } return result; } } /// /// Called when the singleton is enabled to prevent the singleton from being destroyed naturally /// private void OnEnabled() { DontDestroyOnLoad(this); } /// /// Destroys the singleton. /// public static void Destroy() { if (_instance != null) { _lock = new object(); Destroy(_instance); } } /// /// Touches the instance to easily create it without having to assign it. /// public static void TouchInstance() { _ = Instance == null; } } }