協(xié)程與線程的區(qū)別
1、協(xié)程不是線程,也不是異步執(zhí)行的。
2、協(xié)程和 MonoBehaviour 的 Update函數(shù)一樣,也是在MainThread中執(zhí)行的。
3、使用協(xié)程你不用考慮同步和鎖的問題。
4、協(xié)程可以被yield return在當前幀進行打斷,到下一幀后可以繼續(xù)從被打斷的地方繼續(xù)運行。
5、協(xié)程是每幀的LateUpdate()后去運行的。
IEnumerable與IEnumerator的區(qū)別
public interface IEnumerable
{
IEnumerator GetEnumerator();
}
public interface IEnumerator
{
object Current { get; }
bool MoveNext ();
void Reset ();
}
1、一個Collection要支持foreach方式的遍歷,必須實現(xiàn)IEnumerable接口(亦即,必須以某種方式返回IEnumerator object)。
2、IEnumerator object具體實現(xiàn)了iterator(通過MoveNext(),Reset(),Current)。
3、從這兩個接口的用詞選擇上,也可以看出其不同:IEnumerable是一個聲明式的接口,聲明實現(xiàn)該接口的class是“可枚舉(enumerable)”的,但并沒有說明如何實現(xiàn)枚舉器(iterator);IEnumerator是一個實現(xiàn)式的接口,IEnumerator object就是一個iterator。
4、IEnumerable和IEnumerator通過IEnumerable的GetEnumerator()方法建立了連接,client可以通過IEnumerable的GetEnumerator()得到IEnumerator object,在這個意義上,將GetEnumerator()看作IEnumerator object的factory method也未嘗不可。
yield return的常見返回值及其作用
| 常見返回值 | 作用 |
|---|---|
| yield return new WaitForSeconds(3.0f); | 等待3秒,然后繼續(xù)從此處開始,常用于做定時器 |
| yield return null; | 這一幀到此暫停,下一幀再從暫停處繼續(xù),常用于循環(huán)中 |
| yield return new WaitForEndOfFrame(); | 等到這一幀的Cameras和GUI渲染結(jié)束后再從此處繼續(xù),即等到這幀的末尾再往下運行。這行之后的代碼還是在當前幀運行,是在下一幀開始前執(zhí)行,跟return null很相似 |
| yield return new WaitForFixedUpdate(); | 在下一次執(zhí)行FixedUpdate的時候繼續(xù)執(zhí)行這段代碼,即等一次物理引擎的更新 |
| yield return www; | 等待直至異步下載完成 |
| yield break; | 直接跳出協(xié)程,對某些判定失敗必須跳出的時候,比如加載AssetBundle的時候,WWW失敗了,后邊加載bundle沒有必要了,這時候可以yield break跳出。 |
| yield return StartCoroutine(methodName); | 等待另一個協(xié)程執(zhí)行完。這是把協(xié)程串聯(lián)起來的關(guān)鍵,常用于讓多個協(xié)程按順序逐個運行 |
注意:用0或者null來yield的意思是告訴協(xié)程等待下一幀,直到繼續(xù)執(zhí)行為止。
注意事項
1、在程序中調(diào)用StopCoroutine()方法只能終止以字符串形式啟動(開始)的協(xié)程
2、多個協(xié)程可以同時運行,它們會根據(jù)各自的啟動順序來更新
3、協(xié)程可以嵌套任意多層
4、如果你想讓多個腳本訪問一個協(xié)程,那么你可以定義靜態(tài)的協(xié)程
5、協(xié)程不是多線程(盡管它們看上去是這樣的),它們運行在同一線程中,跟普通的腳本一樣
6、如果你的程序需要進行大量的計算,那么可以考慮在一個隨時間進行的協(xié)程中處理它們
7、IEnumerator類型的方法不能帶ref或者out型的參數(shù),但可以帶被傳遞的引用
8、目前在Unity中沒有簡便的方法來檢測作用于對象的協(xié)程數(shù)量以及具體是哪些協(xié)程作用在對象上