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#代码  

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

转载请在文首注明出处:http://dsqiu.iteye.com/blog/2022992

更多精彩请关注D.S.Qiu的博客和微博(ID:静水逐风)

时间: 2024-08-09 19:53:52

Unity协程(Coroutine)管理类——TaskManager工具分享(转)的相关文章

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

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 -- Unit

Unity协程(Coroutine)原理深入剖析(转载)

记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理,而不是从C#底层的语法实现来介绍(后续有需要再进行介绍),一共分为三部分: 线程(

Unity协程(Coroutine)原理深入剖析

尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unity协程的原理的. 本文只是从Unity的角度去分析理解协程的内部运行原理

Unity协程(Coroutine)原理深入剖析再续

Unity协程(Coroutine)原理深入剖析再续 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 前面已经介绍过对协程(Coroutine)的认识和理解,主要讲到了Unity引擎在执行协程(Coroutine)的原理(Unity协程(Coroutine)原理深入剖析)和对协程(Coroutine)状态的控制(Unity协程(Coroutine)管理类--TaskManager工具分享),到这使用Coroutine的疑问就没有了,但是D

【转】Unity协程(Coroutine)原理深入剖析

Unity协程(Coroutine)原理深入剖析 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com 记得去年6月份刚开始实习的时候,当时要我写网络层的结构,用到了协程,当时有点懵,完全不知道Unity协程的执行机制是怎么样的,只是知道函数的返回值是IEnumerator类型,函数中使用yield return ,就可以通过StartCoroutine调用了.后来也是一直稀里糊涂地用,上网google些基本都是例子,很少能帮助深入理解Unit

Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享

Unity多线程(Thread)和主线程(MainThread)交互使用类——Loom工具分享 By D.S.Qiu 尊重他人的劳动,支持原创,转载请注明出处:http.dsqiu.iteye.com           熟悉Unity的developer都知道在Unity中的线程不能使用Unity的对象,但可以使用Unity的值类型变量,如Vector3等.这样就使得线程在Unity中显的很鸡肋和蹩脚,因为很多函数很都是UnityEngine类或函数的调用的,对于哪些是可以在多线程使用,风雨冲

Unity 协程深入解析与原理

先来直接放一段代码 1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class CoroutineTest : MonoBehaviour 6 { 7 8 void Start() 9 { 10 Debug.Log("Start Begin"); 11 12 CustomCoroutine = DelayPrint("Hi"

Unity 协程使用指南

0x00 前言 在使用Unity的过程中,对协程只知道如何使用,但并不知道协程的内部机理,对于自己不清楚的部分就像一块大石压力心里,让自己感觉到担忧和不适.这篇文章一探究竟,彻底揭开协程的面纱,让大家在使用中不再有后顾之忧. 0x01 概念 协程是:程序组件来生成非抢占式多任务子函数,生成的子函数允许在程序里挂起和唤醒操作. 0x02 使用场景 通常协程可以很方便实现延时操作,以及异步加载操作.下面是两个简单协程使用例子. 延时操作 // Use this for initialization

Unity协程使用经验

[Unity协程使用经验] 1.协程的好处是,异步操作发起的地方和结束的地方可以统一在一个方法,这样就不用引入额外的成员变量来进行状态同步. 2.在一个协程中,StartCoroutine()和 yield return StartCoroutine()是不一样的. 前者仅仅是开始一个新的Coroutine,这个新的Coroutine和现有Coroutine并行执行.  后者是返回一个新的Coroutine,当这个新的Coroutine执行完毕后,才继承执行现有Coroutine. 3.由于协程