using UnityEditor;
namespace UnityEngine.ResourceManagement.Util
{
///
/// Creates a singleton.
///
/// The singleton type.
[ExecuteInEditMode]
public abstract class ComponentSingleton : MonoBehaviour where T : ComponentSingleton
{
static T s_Instance;
///
/// Indicates whether or not there is an existing instance of the singleton.
///
public static bool Exists => s_Instance != null;
///
/// Stores the instance of the singleton.
///
public static T Instance
{
get
{
if (s_Instance == null)
{
s_Instance = FindInstance() ?? CreateNewSingleton();
}
return s_Instance;
}
}
static T FindInstance()
{
#if UNITY_EDITOR
foreach (T cb in Resources.FindObjectsOfTypeAll(typeof(T)))
{
var go = cb.gameObject;
if (!EditorUtility.IsPersistent(go.transform.root.gameObject) && !(go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave))
return cb;
}
return null;
#else
return FindObjectOfType();
#endif
}
///
/// Retrieves the name of the object.
///
/// Returns the name of the object.
protected virtual string GetGameObjectName() => typeof(T).Name;
static T CreateNewSingleton()
{
var go = new GameObject();
if (Application.isPlaying)
{
DontDestroyOnLoad(go);
go.hideFlags = HideFlags.DontSave;
}
else
{
go.hideFlags = HideFlags.HideAndDontSave;
}
var instance = go.AddComponent();
go.name = instance.GetGameObjectName();
return instance;
}
private void Awake()
{
if (s_Instance != null && s_Instance != this)
{
DestroyImmediate(gameObject);
return;
}
s_Instance = this as T;
}
///
/// Destroys the singleton.
///
public static void DestroySingleton()
{
if (Exists)
{
DestroyImmediate(Instance.gameObject);
s_Instance = null;
}
}
#if UNITY_EDITOR
void OnEnable()
{
EditorApplication.playModeStateChanged += PlayModeChanged;
}
void OnDisable()
{
EditorApplication.playModeStateChanged -= PlayModeChanged;
}
void PlayModeChanged(PlayModeStateChange state)
{
if (state == PlayModeStateChange.ExitingPlayMode)
{
if (Exists)
{
DestroyImmediate(Instance.gameObject);
s_Instance = null;
}
}
}
#endif
}
}