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

weixin_34126215發表於2014-05-03

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

By D.S.Qiu

尊重他人的勞動,支援原創,轉載請註明出處: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);  
    }  
}  

 

  

 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));  
/// }  
/// ----------------------------------------------------------------------------  
 

 

 

小結:

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

       

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

       轉載請在文首註明出處:http://dsqiu.iteye.com/blog/2022992

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

 

 

 

 

 

 

參考:

krockot / Unity-TaskManagerhttps://github.com/krockot/Unity-TaskManager

②Programmer Instincts:http://programmerinstincts.com/214/

相關文章