您的位置:首页 > 移动开发 > Unity3D

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

2015-11-23 18:47 417 查看
博客分类:

Unity3D插件学习,工具分享

源码分析

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 :

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


/// 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)交流,您的鼓励和支持是我前进的动力,希望能有更多更好的分享。

转载请在文首注明出处:/article/3759466.html

更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: