必讀好文推薦:函數
上面的文章說得太透徹,因此這裏就記一下本身的學習筆記了。this
首先要說明的是,協程並非線程,協程是運行在主線程中的,是和主線程同步執行的代碼,不一樣的地方是運行的方法能夠被yield return在當前幀進行打斷,到下一幀後能夠繼續從被打斷的地方繼續運行。spa
下面咱們看一個示例,場景中有一個空的GameObject對象,其綁定了下面的腳本:線程
1 using UnityEngine; 2 using System.Collections; 3 4 public class Test : MonoBehaviour 5 { 6 int frame = 0; 7 8 void Start () 9 { 10 this.StartCoroutine(CountDown()); 11 } 12 13 void Update () 14 { 15 Debug.Log("Now is frame: " + (++frame)); 16 } 17 18 IEnumerator CountDown() 19 { 20 Debug.Log("step - 1"); 21 yield return null; 22 Debug.Log("step - 2"); 23 yield return null; 24 Debug.Log("step - 3"); 25 yield return null; 26 Debug.Log("step - 4"); 27 } 28 }
下面是執行的結果:3d
下面咱們看看運行的邏輯是如何的:code
當進入Start方法時開始啓動協程,這時候協程開始運行,輸出「step1」後遇到第一個yield return後暫停本幀的運行,接下來進入Update方法輸出「frame1」,因爲協程調用是在Update以後,因此第二幀開始後,先執行了第二個Update輸出「frame2」,而後從協程的上次暫停處繼續執行,輸出「step2」後遇到第二個yield return後暫停本幀的運行,如此反覆,當輸出「step4」後發現方法已經執行完畢,協程結束。協程
下面看看yield break的效果,這個語句會當即中斷協程的運行,代碼以下:對象
1 using UnityEngine; 2 using System.Collections; 3 4 public class Test : MonoBehaviour 5 { 6 int frame = 0; 7 8 void Start () 9 { 10 this.StartCoroutine(CountDown()); 11 } 12 13 void Update () 14 { 15 Debug.Log("Now is frame: " + (++frame)); 16 } 17 18 IEnumerator CountDown() 19 { 20 Debug.Log("step - 1"); 21 yield return null; 22 Debug.Log("step - 2"); 23 yield return null; 24 Debug.Log("step - 3"); 25 yield break; 26 Debug.Log("step - 4"); 27 } 28 }
下面是運行的結果:
咱們能夠發現「step4」已經運行不到了。
yield的返回值,咱們能夠返回null或者數字0,效果是一致的,同時還能夠返回3個對象,分別以下:
yield return new WaitForFixedUpdate();
·等待直到下一個固定幀速率更新函數。
yield return new WaitForEndOfFrame();
·等待直到全部的攝像機和GUI被渲染完成後,在該幀顯示在屏幕以前。
yield return new WaitForSeconds(1);
·在給定的秒數內,暫停協同程序的執行。
下面咱們來看一個例子,修改第一個例子的Test.cs:
1 using UnityEngine; 2 using System.Collections; 3 4 public class Test : MonoBehaviour 5 { 6 int frame1 = 0; 7 int frame2 = 0; 8 int frame3 = 0; 9 10 void Start () 11 { 12 this.StartCoroutine(CountDown()); 13 this.StartCoroutine(CountDown_WaitForFixedUpdate()); 14 this.StartCoroutine(CountDown_WaitForEndOfFrame()); 15 this.StartCoroutine(CountDown_WaitForSeconds()); 16 } 17 18 void Update () 19 { 20 Debug.Log("Update is frame: " + (++frame1)); 21 } 22 23 void FixedUpdate () 24 { 25 Debug.Log("FixedUpdate is frame: " + (++frame2)); 26 } 27 28 void LateUpdate () 29 { 30 Debug.Log("LateUpdate is frame: " + (++frame3)); 31 } 32 33 IEnumerator CountDown() 34 { 35 Debug.Log("yield - step - 1"); 36 yield return null; 37 Debug.Log("yield - step - 2"); 38 yield return null; 39 Debug.Log("yield - step - 3"); 40 } 41 42 IEnumerator CountDown_WaitForFixedUpdate() 43 { 44 Debug.Log("yield WaitForFixedUpdate - step - 1"); 45 yield return new WaitForFixedUpdate(); 46 Debug.Log("yield WaitForFixedUpdate - step - 2"); 47 yield return new WaitForFixedUpdate(); 48 Debug.Log("yield WaitForFixedUpdate - step - 3"); 49 } 50 51 IEnumerator CountDown_WaitForEndOfFrame() 52 { 53 Debug.Log("yield WaitForEndOfFrame - step - 1"); 54 yield return new WaitForEndOfFrame(); 55 Debug.Log("yield WaitForEndOfFrame - step - 2"); 56 yield return new WaitForEndOfFrame(); 57 Debug.Log("yield WaitForEndOfFrame - step - 3"); 58 } 59 60 IEnumerator CountDown_WaitForSeconds() 61 { 62 Debug.Log("yield WaitForSeconds - step - 1"); 63 yield return new WaitForSeconds(1 / 60 * 3);//大概是三幀的時間 64 Debug.Log("yield WaitForSeconds - step - 2"); 65 yield return new WaitForSeconds(1 / 60 * 3); 66 Debug.Log("yield WaitForSeconds - step - 3"); 67 } 68 }
運行的結果以下,有點長,我就弄成兩張圖了:
經過輸出咱們能夠得出下面的結果:
最後補一張開頭博客的運行順序圖: