Unity协程(Coroutine)管理类——TaskManager工具分享

发表于2016-01-27
评论0 1.6k浏览



尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com

     

        在分享 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.   
  9. using UnityEngine;  
  10. using System.Collections;  
  11.   
  12. /// A Task object represents a coroutine.  Tasks can be started, paused, and stopped.  
  13. /// It is an error to attempt to start a task that has been stopped or which has  
  14. /// naturally terminated.  
  15. public class Task  
  16. {  
  17.     /// Returns true if and only if the coroutine is running.  Paused tasks  
  18.     /// are considered to be running.  
  19.     public bool Running {  
  20.         get {  
  21.             return task.Running;  
  22.         }  
  23.     }  
  24.       
  25.     /// Returns true if and only if the coroutine is currently paused.  
  26.     public bool Paused {  
  27.         get {  
  28.             return task.Paused;  
  29.         }  
  30.     }  
  31.       
  32.     /// Delegate for termination subscribers.  manual is true if and only if  
  33.     /// the coroutine was stopped with an explicit call to Stop().  
  34.     public delegate void FinishedHandler(bool manual);  
  35.       
  36.     /// Termination event.  Triggered when the coroutine completes execution.  
  37.     public event FinishedHandler Finished;  
  38.   
  39.     /// Creates a new Task object for the given coroutine.  
  40.     ///  
  41.     /// If autoStart is true (default) the task is automatically started  
  42.     /// upon construction.  
  43.     public Task(IEnumerator c, bool autoStart = true)  
  44.     {  
  45.         task = TaskManager.CreateTask(c);  
  46.         task.Finished += TaskFinished;  
  47.         if(autoStart)  
  48.             Start();  
  49.     }  
  50.       
  51.     /// Begins execution of the coroutine  
  52.     public void Start()  
  53.     {  
  54.         task.Start();  
  55.     }  
  56.   
  57.     /// Discontinues execution of the coroutine at its next yield.  
  58.     public void Stop()  
  59.     {  
  60.         task.Stop();  
  61.     }  
  62.       
  63.     public void Pause()  
  64.     {  
  65.         task.Pause();  
  66.     }  
  67.       
  68.     public void Unpause()  
  69.     {  
  70.         task.Unpause();  
  71.     }  
  72.       
  73.     void TaskFinished(bool manual)  
  74.     {  
  75.         FinishedHandler handler = Finished;  
  76.         if(handler != null)  
  77.             handler(manual);  
  78.     }  
  79.       
  80.     TaskManager.TaskState task;  
  81. }  
  82.   
  83. class TaskManager : MonoBehaviour  
  84. {  
  85.     public class TaskState  
  86.     {  
  87.         public bool Running {  
  88.             get {  
  89.                 return running;  
  90.             }  
  91.         }  
  92.   
  93.         public bool Paused  {  
  94.             get {  
  95.                 return paused;  
  96.             }  
  97.         }  
  98.   
  99.         public delegate void FinishedHandler(bool manual);  
  100.         public event FinishedHandler Finished;  
  101.   
  102.         IEnumerator coroutine;  
  103.         bool running;  
  104.         bool paused;  
  105.         bool stopped;  
  106.           
  107.         public TaskState(IEnumerator c)  
  108.         {  
  109.             coroutine = c;  
  110.         }  
  111.           
  112.         public void Pause()  
  113.         {  
  114.             paused = true;  
  115.         }  
  116.           
  117.         public void Unpause()  
  118.         {  
  119.             paused = false;  
  120.         }  
  121.           
  122.         public void Start()  
  123.         {  
  124.             running = true;  
  125.             singleton.StartCoroutine(CallWrapper());  
  126.         }  
  127.           
  128.         public void Stop()  
  129.         {  
  130.             stopped = true;  
  131.             running = false;  
  132.         }  
  133.           
  134.         IEnumerator CallWrapper()  
  135.         {  
  136.             yield return null;  
  137.             IEnumerator e = coroutine;  
  138.             while(running) {  
  139.                 if(paused)  
  140.                     yield return null;  
  141.                 else {  
  142.                     if(e != null && e.MoveNext()) {  
  143.                         yield return e.Current;  
  144.                     }  
  145.                     else {  
  146.                         running = false;  
  147.                     }  
  148.                 }  
  149.             }  
  150.               
  151.             FinishedHandler handler = Finished;  
  152.             if(handler != null)  
  153.                 handler(stopped);  
  154.         }  
  155.     }  
  156.   
  157.     static TaskManager singleton;  
  158.   
  159.     public static TaskState CreateTask(IEnumerator coroutine)  
  160.     {  
  161.         if(singleton == null) {  
  162.             GameObject go = new GameObject("TaskManager");  
  163.             singleton = go.AddComponent<TaskManager>();  
  164.         }  
  165.         return new TaskState(coroutine);  
  166.     }  
  167. }  

   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的代码。

       

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引