Unity3D之協程(Coroutines & Yield )


寫游戲代碼,往往最終需要代碼為連續的事件.結果會像這樣:
[它可以實現將一段程序延遲執行或者將其各個部分分布在一個時間段內連續執行。]

[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">private int state = 0;  
  2. void Update()  
  3. {  
  4.         if (state == 0)   
  5.         {  
  6.                 //做步驟0  
  7.                 state = 1;  
  8.                 return;  
  9.         }  
  10.         if (state == 1)   
  11.         {  
  12.                 // 做步驟1  
  13.                 state = 2;  
  14.                 return;  
  15.         }  
  16.         // ...  
  17. } </span>  


往往使用yield語句更為方便.yield語句是一個特殊的返回類型,它確保函數從yield語句的下一行繼續執行.


[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">while(true) {  
  2.         // 做步驟0  
  3.         yield return 0;  
  4.          // 等待一幀  
  5.         // 做步驟1  
  6.         yield return 2;  
  7.          // 等待兩幀  
  8.         // ...  
  9. } </span>  


你也可以傳遞時間值到yield語句,Update函數會在yield結束后執行下一語句.

[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">  // do something  
  2.   yield return WaitForSeconds  (5.0);  
  3.   //等待5秒  
  4.   // do something more...  </span>  

你可以入棧並連接協程.


這個例子將執行Do,但是do函數之后的print指令會立刻執行.


[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">Do ();  
  2. Console.WriteLine("This is printed immediately");  
  3. IEnumerator  Do ()  
  4. {  
  5.     Console.WriteLine("Do now");  
  6.     yield return new WaitForSeconds  (2);        
  7.     Console.WriteLine("Do 2 seconds later");  
  8. } </span>  


這個例子將執行Do,並等待,直到Do完成再執行其他語句.【注:這里的等待是把線程時間交給其他任務,而不是阻塞式等待】


[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">// 啟動協程  
  2. yield return StartCoroutine("Do");  
  3. Console.WriteLine("Also after 2 seconds");  
  4. Console.WriteLine ("這個print將在Do協程執行完以后顯示。");  
  5. IEnumerator  Do ()  
  6. {        
  7. Console.WriteLine("Do now");  
  8. yield return new WaitForSeconds  (2);  
  9. Console.WriteLine("Do 2 seconds later");  
  10. }  
  11. </span>  


任何事件處理程序都可以是協同程序 。


注意你不能在Update或FixedUpdate函數內使用yield,但是你能使用 StartCoroutine  開始一個函數.


查看 YieldInstruction , WaitForSeconds , WaitForFixedUpdate , Coroutine  and MonoBehaviour.StartCoroutine  可以獲得更多使用yield的信息.
yield return可以看做是一種特殊的return,會返回到父類繼續執行,但是yield return后面的類型或方法會有一個執行條件,當條件滿足時會回調包含yield的子函數,例如下面代碼
例1:


[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">void Start () {  
  2.   
  3.   
  4.         print("Starting:" + Time.time);  
  5.   
  6.   
  7.         StartCoroutine(WaitAnPrint(2.0F));  
  8.   
  9.   
  10.         print("Before WaiAndPrint:" + Time.time);  
  11.   
  12.   
  13.     }  
  14.   
  15.   
  16. IEnumerator WaitAndPrint(float waitTime)  
  17.   
  18.   
  19.     {  
  20.   
  21.   
  22.         yield return new WaitForSeconds(waitTime);  
  23.   
  24.   
  25.         print("WaitAndPrint:" + Time.time);      
  26.   
  27.   
  28.     }  
  29. </span>  


在執行yield return new WaitForSeconds(waitTime)時暫停的條件沒有滿足,故返回到start函數中繼續執行,直到滿足條件后再回調WaitAndPrint,所以輸出為:


Starting:0


Before WaiAndPrint:0


WaitAndPrint:2.12291


例2:


[csharp]  view plain copy print ?
 
  1. <span style="font-size:18px;">IEnumerator Start()  
  2.   
  3.   
  4.     {  
  5.   
  6.   
  7.         print("starting:" + Time.time);  
  8.   
  9.   
  10.         yield return StartCoroutine(WaitAndPrint(2.0F));  
  11.   
  12.   
  13.         print("done:" + Time.time);  
  14.   
  15.   
  16.     }  
  17.   
  18.   
  19. IEnumerator WaitAndPrint(float waitTime)  
  20.   
  21.   
  22.     {  
  23.   
  24.   
  25.         yield return new WaitForSeconds(waitTime);  
  26.   
  27.   
  28.         print("WaitAndPrint:" + Time.time);      
  29.   
  30.   
  31.     }</span>  



因為start為頂級函數,所以會阻塞在這里,直到StartCoroutine(WaitAndPrint(2.0F))執行完畢,輸出為:


starting:0

WaitAndPrint:2.00315

done:2.00315
[csharp]  view plain copy print ?
 
  1. <pre name="code" class="csharp"><pre name="code" class="csharp"><pre name="code" class="csharp"><p></p><pre></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6. <pre></pre>  
  7. <pre></pre>  
  8. <pre></pre>  
  9. <pre></pre>  
  10. <pre></pre>  
  11. <pre></pre>  
  12. <pre></pre>  
  13. <pre></pre>  
  14. <pre></pre>  
  15. <pre></pre>  
  16. <pre></pre>  
  17. <pre></pre>  
  18. <pre></pre>  
  19. <pre></pre>  
  20.   
  21. </pre></pre></pre>  
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM