// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved. // This code can only be used under the standard Unity Asset Store End User License Agreement // A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms using Doozy.Runtime.Common.Attributes; using UnityEngine; // ReSharper disable MemberCanBePrivate.Global // ReSharper disable CheckNamespace namespace Doozy.Runtime.Common { /// Base MonoBehaviour clas that implements the singleton pattern /// Class type public abstract class SingletonBehaviour : MonoBehaviour where T : MonoBehaviour { /// Flag that returns TRUE if the application is quitting [ClearOnReload(false)] // ReSharper disable once StaticMemberInGenericType public static bool IsQuitting; /// Lock object used to make the singleton thread safe [ClearOnReload(false)] // ReSharper disable once StaticMemberInGenericType private static readonly object Lock = new object(); [ClearOnReload] private static T s_instance; /// Get singleton instance public static T instance { get { if (IsQuitting) return null; lock (Lock) { if (s_instance != null) return s_instance; #if UNITY_2023_1_OR_NEWER T[] instances = FindObjectsByType(FindObjectsSortMode.None); #else T[] instances = FindObjectsOfType(); #endif int count = instances.Length; if (count == 1) return s_instance = instances[0]; if (count > 0) { Debug.LogWarning($"There are {count} instances of the singleton behaviour of type {typeof(T).Name}. There should only be one. Keeping the first one and destroying the rest."); for (int i = 1; i < count; i++) Destroy(instances[i]); return s_instance = instances[0]; } s_instance = new GameObject(typeof(T).Name).AddComponent(); return s_instance; } } } protected virtual void Awake() { if (s_instance != null && s_instance != this) { Debug.Log($"There cannot be two '{typeof(T).Name}' active at the same time. Destroying the '{gameObject.name}' GameObject!"); Destroy(gameObject); return; } s_instance = GetComponent(); DontDestroyOnLoad(gameObject); } protected virtual void OnDestroy() { if (s_instance == this) s_instance = null; } private void OnApplicationQuit() { IsQuitting = true; } } }