using System; using UnityEngine; namespace Core { public abstract class Singleton : MonoBehaviour where T : Singleton { private static T _instance; public static T Instance { get { if (!HasInstance) { Debug.LogWarning( $"Trying to access a singleton of type {typeof(T).Name} that is not in the scene. " + "If you are trying to see if the Instance exists, you should use the HasInstance static property instead."); } return _instance; } } private bool _destroyedByScript; public static bool HasInstance => _instance != null; protected virtual void Awake() { _destroyedByScript = false; if (HasInstance) { Debug.Log($"Two or more instances of a singleton of type {typeof(T).Name} were found in the scene. " + "The new instance of the singleton trying to register will be removed."); DestroyInstance(); return; } try { _instance = (T) Convert.ChangeType(this, typeof(T)); } catch (InvalidCastException) { Debug.Assert(false, "Singleton's T type should be the derived class."); } } private void DestroyInstance() { _destroyedByScript = true; if (gameObject.GetNumberOfComponents() == 1) { Destroy(gameObject); } else { Destroy(this); } } protected virtual void OnDestroy() { if (_instance == this) { _instance = null; } else if (!_destroyedByScript) { Debug.LogWarning($"Instance of {typeof(T).Name} deleted, but was not the singleton instance."); } } } }