1. 程式人生 > >Unity協程(Coroutine)管理類——TaskManager工具分享

Unity協程(Coroutine)管理類——TaskManager工具分享

 在分享 vp_Timer 中提到,沒有繼承的MonoBehaviour,沒有Update,InVoke 和StartCoroutine的機制,vp_Timer就是提供了InVoke的機制,而且還可以統一管理。本篇D.S.Qiu要分享的TaskManager就是一個協程 管理類。 TaskManager —— Unity3D Managed Coroutines with Start, Stop, Resume ,看著就覺得很強大,當然是對於我這種對協程理解不深的來說。下面貼出 The Motivation of the author:

          /// The motivation for this is twofold:

         ///

         /// 1. The existing coroutine API provides no means of stopping specific

        ///    coroutines; StopCoroutine only takes a string argument, and it stops

       ///    all coroutines started with that same string; there is no way to stop

       ///    coroutines which were started directly from an enumerator.  This is

       ///    not robust enough and is also probably pretty inefficient.

       ///

       /// 2. StartCoroutine and friends are MonoBehaviour methods.  This means

       ///    that in order to start a coroutine, a user typically must have some

      ///    component reference handy.  There are legitimate cases where such a

      ///    constraint is inconvenient.  This implementation hides that

      ///    constraint from the user.

       程式碼很簡單,但卻很解渴,Unity官方只聽過了StopCoroutine(string methodName)或StopAllCoroutine() 這兩個停止方法,從api就會覺得Unity的整體方法論還不完善,所以才會覺得TaskManager的難能可貴。由於原始碼簡單,就不做解釋了,See source for document :

C#程式碼 

 收藏程式碼

  1. /// Simple, really.  There is no need to initialize or even refer to TaskManager.  
  2. /// When the first Task is created in an application, a "TaskManager" GameObject  
  3. /// will automatically be added to the scene root with the TaskManager component  
  4. /// attached.  This component will be responsible for dispatching all coroutines  
  5. /// behind the scenes.  
  6. ///  
  7. /// Task also provides an event that is triggered when the coroutine exits.  
  8. using UnityEngine;  
  9. using System.Collections;  
  10. /// A Task object represents a coroutine.  Tasks can be started, paused, and stopped.  
  11. /// It is an error to attempt to start a task that has been stopped or which has  
  12. /// naturally terminated.  
  13. public class Task  
  14. {  
  15.     /// Returns true if and only if the coroutine is running.  Paused tasks  
  16.     /// are considered to be running.  
  17.     public bool Running {  
  18.         get {  
  19.             return task.Running;  
  20.         }  
  21.     }  
  22.     /// Returns true if and only if the coroutine is currently paused.  
  23.     public bool Paused {  
  24.         get {  
  25.             return task.Paused;  
  26.         }  
  27.     }  
  28.     /// Delegate for termination subscribers.  manual is true if and only if  
  29.     /// the coroutine was stopped with an explicit call to Stop().  
  30.     public delegate void FinishedHandler(bool manual);  
  31.     /// Termination event.  Triggered when the coroutine completes execution.  
  32.     public event FinishedHandler Finished;  
  33.     /// Creates a new Task object for the given coroutine.  
  34.     ///  
  35.     /// If autoStart is true (default) the task is automatically started  
  36.     /// upon construction.  
  37.     public Task(IEnumerator c, bool autoStart = true)  
  38.     {  
  39.         task = TaskManager.CreateTask(c);  
  40.         task.Finished += TaskFinished;  
  41.         if(autoStart)  
  42.             Start();  
  43.     }  
  44.     /// Begins execution of the coroutine  
  45.     public void Start()  
  46.     {  
  47.         task.Start();  
  48.     }  
  49.     /// Discontinues execution of the coroutine at its next yield.  
  50.     public void Stop()  
  51.     {  
  52.         task.Stop();  
  53.     }  
  54.     public void Pause()  
  55.     {  
  56.         task.Pause();  
  57.     }  
  58.     public void Unpause()  
  59.     {  
  60.         task.Unpause();  
  61.     }  
  62.     void TaskFinished(bool manual)  
  63.     {  
  64.         FinishedHandler handler = Finished;  
  65.         if(handler != null)  
  66.             handler(manual);  
  67.     }  
  68.     TaskManager.TaskState task;  
  69. }  
  70. class TaskManager : MonoBehaviour  
  71. {  
  72.     public class TaskState  
  73.     {  
  74.         public bool Running {  
  75.             get {  
  76.                 return running;  
  77.             }  
  78.         }  
  79.         public bool Paused  {  
  80.             get {  
  81.                 return paused;  
  82.             }  
  83.         }  
  84.         public delegate void FinishedHandler(bool manual);  
  85.         public event FinishedHandler Finished;  
  86.         IEnumerator coroutine;  
  87.         bool running;  
  88.         bool paused;  
  89.         bool stopped;  
  90.         public TaskState(IEnumerator c)  
  91.         {  
  92.             coroutine = c;  
  93.         }  
  94.         public void Pause()  
  95.         {  
  96.             paused = true;  
  97.         }  
  98.         public void Unpause()  
  99.         {  
  100.             paused = false;  
  101.         }  
  102.         public void Start()  
  103.         {  
  104.             running = true;  
  105.             singleton.StartCoroutine(CallWrapper());  
  106.         }  
  107.         public void Stop()  
  108.         {  
  109.             stopped = true;  
  110.             running = false;  
  111.         }  
  112.         IEnumerator CallWrapper()  
  113.         {  
  114.             yield return null;  
  115.             IEnumerator e = coroutine;  
  116.             while(running) {  
  117.                 if(paused)  
  118.                     yield return null;  
  119.                 else {  
  120.                     if(e != null && e.MoveNext()) {  
  121.                         yield return e.Current;  
  122.                     }  
  123.                     else {  
  124.                         running = false;  
  125.                     }  
  126.                 }  
  127.             }  
  128.             FinishedHandler handler = Finished;  
  129.             if(handler != null)  
  130.                 handler(stopped);  
  131.         }  
  132.     }  
  133.     static TaskManager singleton;  
  134.     public static TaskState CreateTask(IEnumerator coroutine)  
  135.     {  
  136.         if(singleton == null) {  
  137.             GameObject go = new GameObject("TaskManager");  
  138.             singleton = go.AddComponent<TaskManager>();  
  139.         }  
  140.         return new TaskState(coroutine);  
  141.     }  
  142. }  

   Usage Example:

C#程式碼 

 收藏程式碼

  1. /// Example usage:  
  2. ///  
  3. /// ----------------------------------------------------------------------------  
  4. /// IEnumerator MyAwesomeTask()  
  5. /// {  
  6. ///     while(true) {  
  7. ///         Debug.Log("Logcat iz in ur consolez, spammin u wif messagez.");  
  8. ///         yield return null;  
  9. ////    }  
  10. /// }  
  11. ///  
  12. /// IEnumerator TaskKiller(float delay, Task t)  
  13. /// {  
  14. ///     yield return new WaitForSeconds(delay);  
  15. ///     t.Stop();  
  16. /// }  
  17. ///  
  18. /// void SomeCodeThatCouldBeAnywhereInTheUniverse()  
  19. /// {  
  20. ///     Task spam = new Task(MyAwesomeTask());  
  21. ///     new Task(TaskKiller(5, spam));  
  22. /// }  
  23. /// ----------------------------------------------------------------------------  

小結:

       本文主要是分享我的收藏的一些“乾貨”,TaskManager 和 vp_Timer 在專案中發揮了很大的作用,D.S.Qiu 一再覺得強大的東西不都是複雜的,能夠使用最簡單的本質方法解決問題才是程式碼設計的追求。 文末附上了相關的連結以及TaskManager的程式碼。

        如果您對D.S.Qiu有任何建議或意見可以在文章後面評論,或者發郵件([email protected])交流,您的鼓勵和支援是我前進的動力,希望能有更多更好的分享。

更多精彩請關注D.S.Qiu的部落格和微博(ID:靜水逐風)

參考: