///<summary> /// 普通单例创建类 ///</summary> internalstaticclassSingletonCreator { static T CreateNonPublicConstructorObject<T>() where T : class { var type = typeof(T); // 获取私有构造函数 var constructorInfos = type.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
// 获取无参构造函数 var ctor = Array.Find(constructorInfos, c => c.GetParameters().Length == 0);
if (ctor == null) { thrownew Exception("Non-Public Constructor() not found! in " + type); }
return ctor.Invoke(null) as T; }
publicstatic T CreateSingleton<T>() where T : class, ISingleton { var type = typeof(T); var monoBehaviourType = typeof(MonoBehaviour);
if (monoBehaviourType.IsAssignableFrom(type)) { return CreateMonoSingleton<T>(); } else { var instance = CreateNonPublicConstructorObject<T>(); instance.OnSingletonInit(); return instance; } }
///<summary> /// 泛型方法:创建MonoBehaviour单例 ///</summary> ///<typeparam name="T"></typeparam> ///<returns></returns> publicstatic T CreateMonoSingleton<T>() where T : class, ISingleton { T instance = null; var type = typeof(T);
//判断T实例存在的条件是否满足 if (!IsUnitTestMode && !Application.isPlaying) return instance;
//判断当前场景中是否存在T实例 instance = UnityEngine.Object.FindObjectOfType(type) as T; if (instance != null) { instance.OnSingletonInit(); return instance; }
//MemberInfo:获取有关成员属性的信息并提供对成员元数据的访问 MemberInfo info = typeof(T); //获取T类型 自定义属性,并找到相关路径属性,利用该属性创建T实例 var attributes = info.GetCustomAttributes(true); foreach (var atribute in attributes) { var defineAttri = atribute as MonoSingletonPath; if (defineAttri == null) { continue; }
//如果还是无法找到instance 则主动去创建同名Obj 并挂载相关脚本 组件 if (instance == null) { var obj = new GameObject(typeof(T).Name); if (!IsUnitTestMode) UnityEngine.Object.DontDestroyOnLoad(obj); instance = obj.AddComponent(typeof(T)) as T; }
instance.OnSingletonInit(); return instance; }
///<summary> /// 在GameObject上创建T组件(脚本) ///</summary> ///<typeparam name="T"></typeparam> ///<param name="path">路径(应该就是Hierarchy下的树结构路径)</param> ///<param name="dontDestroy">不要销毁 标签</param> ///<returns></returns> privatestatic T CreateComponentOnGameObject<T>(string path, bool dontDestroy) where T : class { var obj = FindGameObject(path, true, dontDestroy); if (obj == null) { obj = new GameObject("Singleton of " + typeof(T).Name); if (dontDestroy && !IsUnitTestMode) { UnityEngine.Object.DontDestroyOnLoad(obj); } }
///<summary> /// Singleton design pattern ///</summary> ///<value>The instance.</value> publicstatic T Instance { get { if (mInstance == null) { mInstance = FindObjectOfType<T>(); if (mInstance == null) { var obj = new GameObject(); mInstance = obj.AddComponent<T>(); } }
return mInstance; } }
///<summary> /// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it. ///</summary> protectedvirtualvoidAwake() { if (!Application.isPlaying) { return; }
if (mInstance == null) { //If I am the first instance, make me the Singleton mInstance = thisas T; DontDestroyOnLoad(transform.gameObject); mEnabled = true; } else { //If a Singleton already exists and you find //another reference in scene, destroy it! if (this != mInstance) { Destroy(this.gameObject); } } } }
///<summary> /// Singleton design pattern ///</summary> ///<value>The instance.</value> publicstatic T Instance { get { if (mInstance == null) { mInstance = FindObjectOfType<T>(); if (mInstance == null) { GameObject obj = new GameObject(); obj.hideFlags = HideFlags.HideAndDontSave; mInstance = obj.AddComponent<T>(); } }
return mInstance; } }
///<summary> /// On awake, we check if there's already a copy of the object in the scene. If there's one, we destroy it. ///</summary> protectedvirtualvoidAwake() { if (!Application.isPlaying) { return; }
InitializationTime = Time.time;
DontDestroyOnLoad(this.gameObject); // we check for existing objects of the same type T[] check = FindObjectsOfType<T>(); foreach (T searched in check) { if (searched != this) { // if we find another object of the same type (not this), and if it's older than our current object, we destroy it. if (searched.GetComponent<ReplaceableMonoSingleton<T>>().InitializationTime < InitializationTime) { Destroy(searched.gameObject); } } }