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 }