unity本人自实现了一个协程调用。
只是moveNext()的简单协程调用和封装,这个没什么好说的, 网上例子一大堆。
但使用的过程中遇到了几个问题。
1. 自己写的moveNext() 协程不能等待 YieldInstruction 和 CustomYieldInstruction 扩展类。
具体原因 猜测是 yield 底层封装好了,固定了实现,并没有把其他的接口暴露出来。
2. 无法等待继承 IEnumerator 在moveNext() 函数里面返回true的协程写法。
原理 每次IEnumerator.MoveNext() 会自动跳转到上次执行的代码后面。应该是底层记录了上次的执行信息。
StartCoroutine在MoveNext()返回true的时候,应该会继续卡在当前位置。(但是并没有清除当前记录信息的接口暴露给我们,所以我们无法清除当前调用信息)。
上述的两个问题, 导致自实现的, 只能写简单的
IEnumerator func(){
...重复代码 yield return null;
}
这样简单的协程。两方都有不方便的地方。
他自带的协程,基于Monobehaviour,必须保证对象的active 等属性,而且无法定制。复杂的功能,写起来很痛苦。
自己写的话, 代码长,大部分都需要自己造轮子。但是可控, 而且可以加入一些自定义的顺序关系(优先级,id ...)等一系列信息控制。
但反而感觉自己写了个大的TaskManager.Update()的感觉。
还是贴一部分代码吧, 可能是自己学艺不精, 上面两个问题无法解决。
1 public static bool MoveNext(IEnumerator subTask) 2 { 3 bool bIsOk = subTask != null && subTask.MoveNext(); 4 bool bIsSubOk = subTask != null && subTask.Current != null && subTask.Current is IEnumerator && MoveNext(subTask.Current as IEnumerator); 5 return bIsOk || bIsSubOk; 6 } 7 8 public static IEnumerator InternalRoutine(this List<IEnumerator> arrCoroutine) 9 { 10 var arrDel = new List<IEnumerator>(); 11 while (arrCoroutine.Count > 0) 12 { 13 arrDel.Clear(); 14 foreach (var tCoroutine in arrCoroutine) 15 { 16 try 17 { 18 if (MoveNext(tCoroutine) == false) 19 { 20 arrDel.Add(tCoroutine); 21 } 22 } 23 catch (Exception ex) 24 { 25 arrDel.Add(tCoroutine); 26 console.log(ex.ToString()); 27 } 28 } 29 foreach (var tCoroutine in arrDel) 30 { 31 arrCoroutine.Remove(tCoroutine); 32 } 33 if (arrCoroutine.Count > 0) 34 yield return null; 35 } 36 }