美文网首页Unity技术分享Unity教程合集unity
Unity协程(Coroutine)管理类——TaskManag

Unity协程(Coroutine)管理类——TaskManag

作者: Babybus_Unity | 来源:发表于2015-12-17 16:35 被阅读502次

    Babybus-u3d技术交流-Unity协程(Coroutine)管理类——TaskManager工具分享

    尊重他人的劳动,支持原创,转载请注明出处: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#代码

    
    /// Simple, really.  There is no need to initialize or even refer to TaskManager.
     
    
    /// When the first Task is created in an application, a "TaskManager" GameObject
     
    
    /// will automatically be added to the scene root with the TaskManager component
     
    
    /// attached.  This component will be responsible for dispatching all coroutines
     
    
    /// behind the scenes.
     
    
    ///
     
    
    /// Task also provides an event that is triggered when the coroutine exits.
     
    
     
    
    using UnityEngine;  
    
    using System.Collections;  
    
     
    
    /// A Task object represents a coroutine.  Tasks can be started, paused, and stopped.
     
    
    /// It is an error to attempt to start a task that has been stopped or which has
     
    
    /// naturally terminated.
     
    
    public class Task  
    {  
    
       /// Returns true if and only if the coroutine is running.  Paused tasks
     
    
       /// are considered to be running.
     
       public bool Running {  
          get {  
    
              return task.Running;  
                 }  
       }  
    
         
    
       /// Returns true if and only if the coroutine is currently paused.
     
    
       public bool Paused {  
    
           get {  
    
              return task.Paused;  
    
          }  
    
      }  
    
         
    
       /// Delegate for termination subscribers.  manual is true if and only if
     
    
       /// the coroutine was stopped with an explicit call to Stop().
     
    
       public delegate void FinishedHandler(bool manual);  
    
         
    
       /// Termination event.  Triggered when the coroutine completes execution.
     
    
       public event FinishedHandler Finished;  
    
     
    
       /// Creates a new Task object for the given coroutine.
     
    
       ///
     
    
       /// If autoStart is true (default) the task is automatically started
     
    
       /// upon construction.
     
    
       public Task(IEnumerator c, bool autoStart = true)  
       {  
    
           task = TaskManager.CreateTask(c);  
    
           task.Finished += TaskFinished;  
    
           if(autoStart)  
    
              Start();  
      }  
    
         
    
       /// Begins execution of the coroutine
     
    
       public void Start()  
    
       {  
    
           task.Start();  
    
       }  
    
     
    
       /// Discontinues execution of the coroutine at its next yield.
     
    
       public void Stop()  
    
       {  
    
           task.Stop();  
    
       }  
    
         
    
       public void Pause()  
    
      {  
    
           task.Pause();  
    
       }  
    
         
    
       public void Unpause()  
       {  
    
           task.Unpause();  
    
       }  
    
         
    
       void TaskFinished(bool manual)  
    
       {  
    
           FinishedHandler handler = Finished;  
    
           if(handler != null)  
    
               handler(manual);  
    
       }  
    
         
    
       TaskManager.TaskState task;  
    
    }  
    
     
    
    class TaskManager : MonoBehaviour  
    
    {  
    
       public class TaskState  
    
      {  
    
           public bool Running {  
    
               get
    {  
    
                   return running;  
    
               }  
    
           }  
    
     
    
           public bool Paused  {  
    
               get
    {  
    
                   return paused;  
    
               }  
    
           }  
    
     
    
           public delegate void FinishedHandler(bool manual);  
           public event FinishedHandler Finished;  
    
     
           IEnumerator coroutine;  
    
           bool running;  
    
           bool paused;  
    
           bool stopped;  
             
    
           public TaskState(IEnumerator c)  
    
           {  
    
               coroutine = c;  
    
           }  
    
             
    
           public void Pause()  
    
           {  
    
               paused = true;  
    
           }  
    
             
    
           public void Unpause()  
    
          {  
    
               paused = false;  
    
           }  
    
             
    
           public void Start()  
    
           {  
    
               running = true;  
    
               singleton.StartCoroutine(CallWrapper());  
    
           }  
    
             
    
           public void Stop()  
    
          {  
               stopped = true;  
    
               running = false;  
    
          }  
    
             
    
           IEnumerator CallWrapper()  
    
           {  
    
               yield return null;  
    
               IEnumerator e = coroutine;  
    
               while(running) {  
    
                   if(paused)  
    
                       yield return null;  
    
                   else {  
    
                       if(e != null&& e.MoveNext()) {  
    
                           yield return e.Current;  
    
                      }  
    
                       else {  
    
                           running = false;  
    
                       }  
    
                   }  
    
               }  
    
                 
    
               FinishedHandler handler = Finished;  
    
               if(handler != null)  
    
                   handler(stopped);  
           }  
    
       }  
    
     
    
       static TaskManager singleton;  
    
     
    
       public static TaskState CreateTask(IEnumerator coroutine)  
       {  
    
           if(singleton == null) {  
    
               GameObject go = new GameObject("TaskManager");  
    
               singleton = go.AddComponent<TaskManager>();  
    
           }  
    
           return new TaskState(coroutine);  
       }  
    }  
    
    /// Simple, really.  There is no need to initialize or even refer to TaskManager./// When the first Task is created in an application, a "TaskManager" GameObject/// will automatically be added to the scene root with the TaskManager component/// attached.  This component will be responsible for dispatching all coroutines/// behind the scenes.////// Task also provides an event that is triggered when the coroutine exits.using UnityEngine;using System.Collections;/// A Task object represents a coroutine.  Tasks can be started, paused, and stopped./// It is an error to attempt to start a task that has been stopped or which has/// naturally terminated.public class Task{    /// Returns true if and only if the coroutine is running.  Paused tasks /// are considered to be running.   public bool Running {       get {           return task.Running;        }   }       /// Returns true if and only if the coroutine is currently paused.  public bool Paused {        get {           return task.Paused;     }   }       /// Delegate for termination subscribers.  manual is true if and only if    /// the coroutine was stopped with an explicit call to Stop().  public delegate void FinishedHandler(bool manual);      /// Termination event.  Triggered when the coroutine completes execution.   public event FinishedHandler Finished;  /// Creates a new Task object for the given coroutine.  /// /// If autoStart is true (default) the task is automatically started    /// upon construction.  public Task(IEnumerator c, bool autoStart = true)   {       task = TaskManager.CreateTask(c);       task.Finished += TaskFinished;      if(autoStart)           Start();    }       /// Begins execution of the coroutine   public void Start() {       task.Start();   }   /// Discontinues execution of the coroutine at its next yield.  public void Stop()  {       task.Stop();    }       public void Pause() {       task.Pause();   }       public void Unpause()   {       task.Unpause(); }       void TaskFinished(bool manual)  {       FinishedHandler handler = Finished;     if(handler != null)         handler(manual);    }       TaskManager.TaskState task;}class TaskManager : MonoBehaviour{  public class TaskState  {       public bool Running {           get {               return running;         }       }       public bool Paused  {           get {               return paused;          }       }       public delegate void FinishedHandler(bool manual);      public event FinishedHandler Finished;      IEnumerator coroutine;      bool running;       bool paused;        bool stopped;               public TaskState(IEnumerator c)     {           coroutine = c;      }               public void Pause()     {           paused = true;      }               public void Unpause()       {           paused = false;     }               public void Start()     {           running = true;         singleton.StartCoroutine(CallWrapper());        }               public void Stop()      {           stopped = true;         running = false;        }               IEnumerator CallWrapper()       {           yield return null;          IEnumerator e = coroutine;          while(running) {                if(paused)                  yield return null;              else {                  if(e != null && e.MoveNext()) {                     yield return e.Current;                 }                   else {                      running = false;                    }               }           }                       FinishedHandler handler = Finished;         if(handler != null)             handler(stopped);       }   }   static TaskManager singleton;   public static TaskState CreateTask(IEnumerator coroutine)   {       if(singleton == null) {         GameObject go = new GameObject("TaskManager");          singleton = go.AddComponent<TaskManager>();     }       return new TaskState(coroutine);    }}
      Usage Example:
    
    C#代码 
    
    
    /// Example usage:
     
    
    ///
     
    
    /// ----------------------------------------------------------------------------
     
    
    /// IEnumerator MyAwesomeTask()
     
    
    /// {
     
    
    ///     while(true) {
     
    
    ///         Debug.Log("Logcat iz in ur consolez, spammin u wif messagez.");
     
    
    ///         yield return null;
     
    
    ////    }
     
    
    /// }
     
    
    ///
     
    
    /// IEnumerator TaskKiller(float delay, Task t)
     
    
    /// {
     
    
    ///     yield return new WaitForSeconds(delay);
     
    
    ///     t.Stop();
     
    
    /// }
     
    
    ///
     
    
    /// void SomeCodeThatCouldBeAnywhereInTheUniverse()
     
    
    /// {
     
    
    ///     Task spam = new Task(MyAwesomeTask());
     
    
    ///     new Task(TaskKiller(5, spam));
     
    
    /// }
     
    
    /// ----------------------------------------------------------------------------
     
    
    /// Example usage:////// ----------------------------------------------------------------------------/// IEnumerator MyAwesomeTask()/// {///     while(true) {///         Debug.Log("Logcat iz in ur consolez, spammin u wif messagez.");///         yield return null;////    }/// }////// IEnumerator TaskKiller(float delay, Task t)/// {///     yield return new WaitForSeconds(delay);///     t.Stop();/// }////// void SomeCodeThatCouldBeAnywhereInTheUniverse()/// {///     Task spam = new Task(MyAwesomeTask());///     new Task(TaskKiller(5, spam));/// }/// ----------------------------------------------------------------------------
    

    小结:
    本文主要是分享我的收藏的一些“干货”,TaskManager 和 vp_Timer 在项目中发挥了很大的作用,D.S.Qiu 一再觉得强大的东西不都是复杂的,能够使用最简单的本质方法解决问题才是代码设计的追求。 文末附上了相关的链接以及TaskManager的代码。

    相关文章

      网友评论

        本文标题:Unity协程(Coroutine)管理类——TaskManag

        本文链接:https://www.haomeiwen.com/subject/amdphttx.html