码迷,mamicode.com
首页 > 编程语言 > 详细

Unity自己实现协程

时间:2017-02-05 19:21:13      阅读:958      评论:0      收藏:0      [点我收藏+]

标签:code   upd   没有   engine   lin   move   tar   执行   枚举   

自己实现协程有几个好处:

  1. 脱离Unity独立,拿到别的地方也可以用。
  2. 非主线程也可以启动协程,然后在主线程执行,比如异步网络消息等。
  3. 可以给每个协程一个id,通过id随时启动或关闭某个特定的协程,或者非MonoBehavior对象也可以管理属于自己的协程。

 

Unity中,Coroutine是在LateUpdate执行的,每一个update都会执行一部分代码,拿IEnumerator来说,就是每一次都会MoveNext一下。

IEnumerator有三个接口:

  • Current:返回一个object,可以设置当前的一个状态。
  • MoveNext:返回true表示没有到最后,返回false表示已经完成枚举。
  • Reset:恢复状态,从头开始枚举。

如果自己写一个返回IEnumerator方法,每次就会MoveNext到一个yield,遇到yield return,MoveNext会返回true,Current值就是return的对象(yield return null时Current=null, yield return obj时Current=obj),遇到yield break,MoveNext会返回false,表示已经执行完毕。但是如果直接调用IEnumerator.MoveNext,不会去对里面的另一个协程MoveNext,下次就跳过了。

 

基于以上内容,可以自己写一个方法对IEnumerator进行MoveNext,以实现自制协程的核心代码:

public static bool MoveNext(IEnumerator subTask)
{
  var child = subTask.Current;
  //yield return另一个协程:递归MoveNext
  if (child != null && child is IEnumerator && MoveNext(child as IEnumerator))
    return true;
  #if UNITY
  //yield return www:等待www完成
  if(child is UnityEngine.WWW && !(child as UnityEngine.WWW).isDone)
    return true;
  #endif
  if (subTask.MoveNext ())
    return true;
   return false;
}

 

管理协程也很简单,用一个链表来管理:

LinkedListNode<IEnumerator> node = m_taskList.First;
LinkedListNode<IEnumerator> tempNode = node;
while (node != null) {                
  if (!MoveNext(node.Value)) {
    tempNode
= node; node = node.Next; //此处可以写删除节点的后续处理 m_taskList.Remove(tempNode); } else { node = node.Next; }
}

 

自己写IEnumerator方法时,return另一个协程不用写yield return StartCoroutine(func()),直接写yield return func()就可以,如:

IEnumerator a()
{
  ...
}

IEnumerator b()
{
  ...
  yield return a();
  ...
}

 

也可以自己写一些实用的IEnumerator类,比如我们项目里用的WaitForEvent, 还有组合类如WaitForAll,WaitForAny等。

Unity自己实现协程

标签:code   upd   没有   engine   lin   move   tar   执行   枚举   

原文地址:http://www.cnblogs.com/drashnane/p/6368307.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!