yield學習續:yield return迭代塊在Unity3D中的應用——協程

必讀好文推薦:函數

Unity協程(Coroutine)原理深刻剖析post

Unity協程(Coroutine)原理深刻剖析再續學習

 

上面的文章說得太透徹,因此這裏就記一下本身的學習筆記了。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 }
複製代碼

運行的結果以下,有點長,我就弄成兩張圖了:

 

經過輸出咱們能夠得出下面的結果:

  1. 當幀數波動時,FixedUpdate會進行屢次補幀處理,咱們能夠發現兩張圖之間FixedUpdate從3一直補幀到15;
  2. WaitForFixedUpdate表示協程是跟在FixedUpdate以後執行的;
  3. WaitForEndOfFrame表示協程是跟在LateUpdate以後執行的;
  4. WaitForSeconds額。。。不用多說了,你指定多久後執行就多久後執行,固然因爲是基於幀運算的,因此可能會不許確;

 

最後補一張開頭博客的運行順序圖:

天道酬勤,功不唐捐!
相關文章
相關標籤/搜索