StartCoroutine和yield return表面意思很好理解,StartCoroutine就是開啟一個協程,yield return 是迭代器塊返回調用迭代的地方。
是吧?不知道你什么感覺,反正我覺得,還是需要深入研究一下的。OK,here we go!
首先,先看一下StartCoroutine在Unity官方的解釋。
意思是:一個協程的執行可以在任何地方用yield語句來暫停,yield return的值決定了什么時候協程恢復執行。協程在協調在幾幀中執行的操作時有極大的用處.協程幾乎沒有任何性能開銷。
StartCoroutine一般都會立即返回,然而你也可以獲得返回結果的值。但是這一步會等到協程結束執行才能生效。
OK,意思應該不難理解,根據他的意思我們來分析一段程序。
運行結果是:
start1
test1
start2
test2
這下就一目了然了,當StartCoroutine剛調用的時候,可以理解為正常的函數調用,然后接着看調用的函數里面。
當被調用函數執行到yield return null;(暫停協程,等待下一幀繼續執行)時,根據Unity解釋協同程序就會被暫停,其實我個人認為他這個解釋不夠精確,先返回開始協程的地方,然后再暫停協程。也就是先通知調用處,“你先走吧,不用管我”,然后再暫停協程。。怎么?不信?那我們再寫個demo驗證一下。
執行結果:
start1
test1
start2
test2 (這個test2是等待三秒后才打印出來的)
正好順便驗證了“yield return的值決定了什么時候協程恢復執行”這句,其實yield return后面的值可以后很多用法,可以看這個帖子:http://blog.sina.com.cn/s/blog_aaa4ce8d010131kr.html
其實再回過頭來想想,協程->協同程序->其實就是協同兩個任務,表面看起來很簡單,但是在一些稍微大點的項目中用起來,對於新手來說還是會有些晦澀。。。
比如說
IEnumerator Init() { yield return StartCoroutine(init1()); Debug.Log("init1 finish"); yield return StartCoroutine(init2()); Debug.Log("init2 finish"); yield return StartCoroutine(init3()); Debug.Log("init3 finish"); } IEnumerator init1() { // 模擬初始化 yield return new WaitForSeconds(2);// } IEnumerator init2() { // do somthing.. yield return new WaitForSeconds(2);// } IEnumerator init2() { // do somthing.. yield return new WaitForSeconds(2);// }
其實就是一個執行順序的問題,這樣調用能保證,init1,init2,init3一個一個的執行,不至於出現后面執行的代碼引用一個前面未初始化的變量。。。
那么,接着這個執行順序的話題,我們在來研究一個話題,看下面代碼
void Start () { Debug.Log("start1"); StartCoroutine(Test()); Debug.Log("start2"); } IEnumerator Test() { Debug.Log("test1"); yield return StartCoroutine(DoSomething()); Debug.Log("test2"); } IEnumerator DoSomething() { Debug.Log("load 1"); yield return null; Debug.Log("load 2"); }
執行結果:
start1
test1
load1
start2
load2
test2
這種StartCoroutine中嵌套一個yield return StartCoroutine,第一個StartCoroutine會等到第二個StartCoroutine中所有代碼結束后再繼續執行,而第二個StartCoroutine中的yield語句會先返回第一個,然后立即返回他的調用處,也就是調用處會繼續執行,而第一個StartCoroutine會等待第二個執行完再繼續執行。
如果還想繼續深入,可以看一下C#中的迭代器,那里面說明了yield和IEnumerator根本到底是什么。
OK,今天就說到這。Good Luck!