Unity自己实现协程

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

  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等。

时间: 2024-08-03 20:06:15

Unity自己实现协程的相关文章

Unity里的协程Coroutines

Unity里的Coroutine在帮助我们实现序列化事件时尤其方便.可以让事件依次发生,可以让事件A等待事件B结束后才开始执行. 但需要厘清几个基本概念. Coroutines不是多线程,不是异步技术.Coroutines都在MainThread中执行,且每个时刻只有一个Coroutine在执行. Coroutine是一个function,可以部分地执行,当条件满足时,未来会被再次执行直到整个函数执行完毕. A coroutine is a function that is executed p

Unity中的协程(一)

这篇文章很不错的问题,推荐阅读英文原版: Introduction to Coroutines Scripting with Coroutines   这篇文章转自:http://blog.csdn.net/huang9012/article/details/38492937 协程介绍 在Unity中,协程(Coroutines)的形式是我最喜欢的功能之一,几乎在所有的项目中,我都会使用它来控制运动,序列,以及对象的行为.在这个教程中,我将会说明协程是如何工作的,并且会附上一些例子来介绍它的用法

Unity中使用协程进行服务端数据验证手段

近期在做项目中的个人中心的一些事情,用户头像上传,下载,本地缓存,二级缓存,压缩,这些都要做,麻雀虽小五脏俱全啊,也是写的浑浑噩噩的, 当我们在上传用户头像的时候,向服务端发送上传头像请求之前,一般都会做一次验证,向服务端获取token验证信息,来确保非法上传,如果不做这个那么会有非法用户上传非法图像,使你的服务器 带来未知的灾难. 而验证的逻辑很好写,并没有什么难度,比如: Server.SendMessage("获取token"); Client.Receive(string to

【Unity】理解协程的原理1——实现一个自己的WaitForSeconds

协程的所能达到的效果就是在指定的时间点上执行需要执行的代码,Unity中开始一个协程的函数是StartCoroutine,而提供的延迟的类有以下几种分别是 new WaitForEndOfFrame; //等待一帧 new WaitForFixedUpdate; //等待一个FixedUpdate(固定时间间隔) new WaitForSeconds; //等待X秒 new WWW; //等待外部资源加载完毕 本文就针对其中的WaitForSeconds实现进行探究. 因为在开发过程中,很多时候

Unity中使用协程实现倒计时功能

unity中协程的功能很强大,能够充分发挥unity协程功能的地方就是游戏的倒计时,今天我们就来实现一个简易版本的倒计时. 新建一个场景,给camera添加一个脚本,脚本内容如下: using UnityEngine; using System.Collections; public class ShowNumber : MonoBehaviour { private int tmp = 10; // Use this for initialization void Start () { //开

【Unity笔记】协程Coroutine的简单优化

一个最简单的协程,也至少需要2帧才能完成.第一帧走到yield return null停止,第二帧从此处接着执行完下面的操作.需求:如果缓存中存在某数据则直接使用,否则联网异步下载. private bool cached; // 该数据是否已有缓存 void Start(){ StartCoroutine(Download()); } IEnumerator WorkWhenDownload() { if(cached){ // 直接使用缓存 }else{ // 没有缓存,联网下载 WWW w

unity里头的协程

1 IEnumerator ie = null; 2 3 void Start() 4 { 5 ie = coroutinFunc(); //这里只是新建了一个协程,并不会执行协程函数里的代码,需要调用StartCoroutine方法或者ie.MoveNex才会执行协程函数里的代码 6 } 7 8 IEnumerator coroutinFunc() 9 { 10 yield return 0; 11 } 在没有调用StartCoroutine方法来执行协程函数的时候,ie.MoveNext才会

Unity中的协程用法以及注意事项

前沿:这章节,将简单的总结一下如何开启协程,关闭协程,以及使用协程的注意事项. 一.如何开启协程: private void Start() { m_SpherePrefab = Resources.Load<GameObject>("Test/Sphere_00"); Debug.Log("m_SpherePrefab = " + m_SpherePrefab); #region 协程的学习及使用 StartCoroutine(Test_00());

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

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