Unity中的单例

由于对单例理解的不是很深,所以在我的印象中,例就是一个比较有规范的全局类。

至于什么多线程可能会有问题,我暂时没接触到。

1.首先是最简单的了,各种语言都可以写的单例

C#:

public class ExpManager
 {
   static ExpManager m_ExpManager = null;

public static ExpManager GetSingleton() { if (null == m_ExpManager) { m_ExpManager = new ExpManager(); } return m_ExpManager; } }

2.Unity中的单例

在Unity中场景的概念分的比较明显,经常有场景间的跳转,而在跳转时会把上一个场景的东西销毁,再创建下一个场景的东西。

但有些东西却是场景共用的,比如说共用的UI,声音播放器等。这时我们就想要一个不会被销毁的东西来承载这些东西。

Unity提供了这个函数:

http://docs.unity3d.com/Documentation/ScriptReference/Object.DontDestroyOnLoad.html

在NGUI中看UpdateManager这个类,可以看到他的单例的实现,还有如何管理自己的Update函数,比如计时器实现时也要用到Update:

public class UpdateManager : MonoBehaviour
 {
     public delegate void OnUpdate (float delta);
 
     public class UpdateEntry
     {
         public int index = 0;
         public OnUpdate func;
         public MonoBehaviour mb;
         public bool isMonoBehaviour = false;
     }
 
     public class DestroyEntry
     {
         public Object obj;
         public float time;
     }
 
     static int Compare (UpdateEntry a, UpdateEntry b)
     {
         if (a.index < b.index) return 1;
         if (a.index > b.index) return 1;
         return 0;
     }
 
     static UpdateManager mInst;
     List<UpdateEntry> mOnUpdate = new List<UpdateEntry>();
     List<UpdateEntry> mOnLate = new List<UpdateEntry>();
     List<UpdateEntry> mOnCoro = new List<UpdateEntry>();
     BetterList<DestroyEntry> mDest = new BetterList<DestroyEntry>();
     float mTime = 0f;
 
     /// <summary>
     /// Ensure that there is an instance of this class present.
     /// </summary>
 
     static void CreateInstance ()
     {
         if (mInst == null)
         {
             mInst = GameObject.FindObjectOfType(typeof(UpdateManager)) as UpdateManager;
 
             if (mInst == null && Application.isPlaying)
             {
                 GameObject go = new GameObject("_UpdateManager");
                 DontDestroyOnLoad(go);
                 //go.hideFlags = HideFlags.HideAndDontSave;
                 mInst = go.AddComponent<UpdateManager>();
             }
         }
     }
 
     /// <summary>
     /// Update the specified list.
     /// </summary>
 
     void UpdateList (List<UpdateEntry> list, float delta)
     {
         for (int i = list.Count; i > 0; )
         {
             UpdateEntry ent = list[--i];
 
             // If it's a monobehaviour we need to do additional checks
             if (ent.isMonoBehaviour)
             {
                 // If the monobehaviour is null, remove this entry
                 if (ent.mb == null)
                 {
                     list.RemoveAt(i);
                     continue;
                 }
 
                 // If the monobehaviour or its game object are disabled, move on to the next entry
                 if (!ent.mb.enabled || !ent.mb.gameObject.active) continue;
             }
 
             // Call the function
             ent.func(delta);
         }
     }
 
     /// <summary>
     /// Start the coroutine.
     /// </summary>
 
     void Start ()
     {
         if (Application.isPlaying)
         {
             mTime = Time.realtimeSinceStartup;
             StartCoroutine(CoroutineFunction());
         }
     }
 
     /// <summary>
     /// Don't keep this class around after stopping the Play mode.
     /// </summary>
 
     void OnApplicationQuit () { DestroyImmediate(gameObject); }
 
     /// <summary>
     /// Call all update functions.
     /// </summary>
 
     void Update ()
     {
         if (mInst != this) NGUITools.Destroy(gameObject);
         else UpdateList(mOnUpdate, Time.deltaTime);
     }
 
     /// <summary>
     /// Call all late update functions and destroy this class if no callbacks have been registered.
     /// </summary>
 
     void LateUpdate ()
     {
         UpdateList(mOnLate, Time.deltaTime);
         if (!Application.isPlaying) CoroutineUpdate();
     }
 
     /// <summary>
     /// Call all coroutine update functions and destroy all delayed destroy objects.
     /// </summary>
 
     bool CoroutineUpdate ()
     {
         float time = Time.realtimeSinceStartup;
         float delta = time - mTime;
         if (delta < 0.001f) return true;
 
         mTime = time;
 
         UpdateList(mOnCoro, delta);
 
         bool appIsPlaying = Application.isPlaying;
 
         for (int i = mDest.size; i > 0; )
         {
             DestroyEntry de = mDest.buffer[--i];
 
             if (!appIsPlaying || de.time < mTime)
             {
                 if (de.obj != null)
                 {
                     NGUITools.Destroy(de.obj);
                     de.obj = null;
                 }
                 mDest.RemoveAt(i);
             }
         }
 
         // Nothing left to update? Destroy this game object.
         if (mOnUpdate.Count == 0 && mOnLate.Count == 0 && mOnCoro.Count == 0 && mDest.size == 0)
         {
             NGUITools.Destroy(gameObject);
             return false;
         }
         return true;
     }
 
     /// <summary>
     /// Coroutine update function.
     /// </summary>
 
     IEnumerator CoroutineFunction ()
     {
         while (Application.isPlaying)
         {
             if (CoroutineUpdate()) yield return null;
             else break;
         }
     }
 
     /// <summary>
     /// Generic add function.
     /// Technically 'mb' is not necessary as it can be retrieved by calling 'func.Target as MonoBehaviour'.
     /// Unfortunately Flash export fails to compile with that, claiming the following:
     /// "Error: Access of possibly undefined property Target through a reference with static type Function."
     /// </summary>
 
     void Add (MonoBehaviour mb, int updateOrder, OnUpdate func, List<UpdateEntry> list)
     {
 #if !UNITY_FLASH
         // Flash export fails at life.
         for (int i = 0, imax = list.Count; i < imax; ++i)
         {
             UpdateEntry ent = list[i];
             if (ent.func == func) return;
         }
 #endif
 
         UpdateEntry item = new UpdateEntry();
         item.index = updateOrder;
         item.func = func;
         item.mb = mb;
         item.isMonoBehaviour = (mb != null);
 
         list.Add(item);
         if (updateOrder != 0) list.Sort(Compare);
     }
 
     /// <summary>
     /// Add a new update function with the specified update order.
     /// </summary>
 
     static public void AddUpdate (MonoBehaviour mb, int updateOrder, OnUpdate func) { CreateInstance(); mInst.Add(mb, updateOrder, func, mInst.mOnUpdate); }
 
     /// <summary>
     /// Add a new late update function with the specified update order.
     /// </summary>
 
     static public void AddLateUpdate (MonoBehaviour mb, int updateOrder, OnUpdate func) { CreateInstance(); mInst.Add(mb, updateOrder, func, mInst.mOnLate); }
 
     /// <summary>
     /// Add a new coroutine update function with the specified update order.
     /// </summary>
 
     static public void AddCoroutine (MonoBehaviour mb, int updateOrder, OnUpdate func) { CreateInstance(); mInst.Add(mb, updateOrder, func, mInst.mOnCoro); }
 
     /// <summary>
     /// Destroy the object after the specified delay in seconds.
     /// </summary>
 
     static public void AddDestroy (Object obj, float delay)
     {
         if (obj == null) return;
 
         if (Application.isPlaying)
         {
             if (delay > 0f)
             {
                 CreateInstance();
 
                 DestroyEntry item = new DestroyEntry();
                 item.obj = obj;
                 item.time = Time.realtimeSinceStartup + delay;
                 mInst.mDest.Add(item);
             }
             else Destroy(obj);
         }
         else DestroyImmediate(obj);
     }
 }
原文地址:https://www.cnblogs.com/gameprogram/p/2736856.html