|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Assertions;
|
|
|
|
|
using UnityEngine.SceneManagement;
|
|
|
|
|
|
|
|
|
|
namespace LanLib.Singleton
|
|
|
|
|
{
|
|
|
|
|
[ExecuteInEditMode]
|
|
|
|
|
public class Singleton<T> : SingletonBase where T : Singleton<T>
|
|
|
|
|
{
|
|
|
|
|
private const BindingFlags BindingFlags = System.Reflection.BindingFlags.Default
|
|
|
|
|
| System.Reflection.BindingFlags.FlattenHierarchy
|
|
|
|
|
| System.Reflection.BindingFlags.Static
|
|
|
|
|
| System.Reflection.BindingFlags.Public
|
|
|
|
|
| System.Reflection.BindingFlags.NonPublic;
|
|
|
|
|
|
|
|
|
|
private static T _instance;
|
|
|
|
|
|
|
|
|
|
public static T Instance
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (!_instance)
|
|
|
|
|
{
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
_instance = Resources.FindObjectsOfTypeAll<T>().FirstOrDefault(inst => inst);
|
|
|
|
|
#else
|
|
|
|
|
_instance = FindObjectOfType<T>();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_instance)
|
|
|
|
|
{
|
|
|
|
|
_instance = (T)typeof(T).GetMethod("CreateInstance", BindingFlags)?.Invoke(null, null);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Assert.IsNotNull(_instance);
|
|
|
|
|
return _instance;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected static T CreateInstance()
|
|
|
|
|
{
|
|
|
|
|
return new GameObject(typeof(T).Name)
|
|
|
|
|
{
|
|
|
|
|
hideFlags = HideFlags.HideAndDontSave ^ HideFlags.NotEditable
|
|
|
|
|
}.AddComponent<T>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected virtual void Awake()
|
|
|
|
|
{
|
|
|
|
|
if (_instance == null)
|
|
|
|
|
{
|
|
|
|
|
_instance = this as T;
|
|
|
|
|
if (Application.isPlaying)
|
|
|
|
|
{
|
|
|
|
|
DestroyOnSceneUnload = DestroyOnSceneUnload;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DestroySelf();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public abstract class SingletonBase : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
private SingletonDestroyCondition _destroyCondition = SingletonDestroyCondition.ReloadDomain;
|
|
|
|
|
|
|
|
|
|
public virtual SingletonDestroyCondition DestroyCondition
|
|
|
|
|
{
|
|
|
|
|
get => _destroyCondition;
|
|
|
|
|
private set
|
|
|
|
|
{
|
|
|
|
|
var flgSceneUnload = (value ^ _destroyCondition) & SingletonDestroyCondition.SceneUnload;
|
|
|
|
|
if (flgSceneUnload != 0)
|
|
|
|
|
{
|
|
|
|
|
var hasFlag = 0 != (value & SingletonDestroyCondition.SceneUnload);
|
|
|
|
|
DestroyOnSceneUnload = hasFlag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_destroyCondition = value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool DestroyOnSceneUnload
|
|
|
|
|
{
|
|
|
|
|
get => DestroyCondition.Contains(SingletonDestroyCondition.SceneUnload);
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (value)
|
|
|
|
|
{
|
|
|
|
|
SceneManager.MoveGameObjectToScene(gameObject, SceneManager.GetActiveScene());
|
|
|
|
|
DestroyCondition |= SingletonDestroyCondition.SceneUnload;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DontDestroyOnLoad(gameObject);
|
|
|
|
|
DestroyCondition &= ~SingletonDestroyCondition.SceneUnload;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal void DestroySelf()
|
|
|
|
|
{
|
|
|
|
|
if (Application.isPlaying)
|
|
|
|
|
{
|
|
|
|
|
Destroy(gameObject);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
DestroyImmediate(gameObject);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|