Unity Coroutine詳解(二)

 

•        介紹
•        Part 1. 同步等待
•        Part 2. 異步協程
•        Part 3. 同步協程
•        Part 4. 並行協程
程序員

 

一、介紹
  每一個Unity腳本都有兩個重要的功能:開始和更新。 前者的做用是當一個對象被建立後,在每一幀對後者進行調用。設計規定,下一幀只有更新結束才能開始。這樣會出現一個設計侷限:更新的持續時間不太容易超過一幀。
坦白而言,每一個你能想到的自定義行爲都能用開始和更新進行實現。然而,基於多幀的事件發生要難實現一些(例如動畫,對白,等待,…)。這是由於其設定沒法寫入一個持續的流中,必須分段,分佈在不少幀中。這每每讓代碼難寫,維護也很困難。
若是能在短暫的單幀中不受任何約束那就很是完美了。若是你是程序員,那麼確定知道線程的概念。線程是並行執行的代碼段,使用線程須要謹慎。這是由於當多線程不加限制地共享一個變量會出現問題。Unity的設計並不建議使用線程。然而,Unity提供了折中的方案:協程。協程持續超過一幀的時間。此外,協程能夠在任意狀況下中斷和恢復執行。
協程是常規的C#函數,返回一個IEnumerator。爲了執行協程(並不一樣於以往的函數),必須使用StartCoroutine 方法(UnityDoc)。例如:多線程

void Start ()
{
    // Execute A as a coroutine
    StartCoroutine( A() );
}
  
IEnumerator A ()
{
    ...
}

將A當作協程執行。StartCoroutine 方法當即終止,同時產生新的協程並行執行。異步

 

二、同步等待函數

  若是你以前用過協程,那麼應該已經遇到過WaitForSeconds (float/int)。像繼承YieldInstruction的其它類,它容許協程短暫的暫停。當用yield進行鏈接時, WaitForSeconds提供了一種方式去延遲剩餘代碼的執行。
下面的代碼展現瞭如何使用協程:優化

IEnumerator A()
{
    ...
  
    yield return new WaitForSeconds(10f);
  
    ...
}

UML 的序列圖如上(Wikipedia),驗證了WaitForSeconds的做用。當調用協程(即調用A),它暫停執行,直到消耗必定的時間。這個等待稱爲同步,由於協程等待另外一個操做的完成。動畫

 

三、異步協程spa

  Unity還容許在現有協程中開啓一個新的協程。最簡單的方法就是使用StartCoroutine。這麼調用的話,新生的協程會和之前的協程共存。它們不發生直接交互,最重要的是它們不會相互等待。與以前的同步等待相比,這種狀況是異步的,兩個協程不要試圖保持同步。線程

IEnumerator A()
{
    ...
  
    // Starts B as a coroutine, and continue the execution
    StartCoroutine( B() );
  
    ...
}

須要注意的是,在這個例子中B是一個徹底獨立的協同程序。終止不會影響B,反之亦然。設計

 

四、同步協程code

  能夠執行嵌套的協程並等待其實行完畢。最簡單的辦法就是使用yield返回。

IEnumerator A()
{
    ...
  
    // Waits for B to terminate
    yield return StartCoroutine( B() );
  
    ...
}

值得注意的是,因爲執行B期間暫停了A,這種特殊狀況下不須要啓動另外一個協程。有人可能會像下面這樣試圖優化協程:

IEnumerator A()
{
    ...
  
    // Executes B as part of A
    B();
  
    ...
}

B的執行和普通函數有同樣的效果,不一樣的是B是在單幀內執行的。相反,經過使用StartCoroutine,A已經暫定的同時下一幀能夠開始進行。
引入這個例子是爲了介紹更加複雜的例子,同步協程。

 

五、並行協程

   當協程經過StartCoroutine啓動時,返回了一個特殊的對象。 這能夠用來查詢協程的狀態,隨時等待其結束。
下面的例子中,協程B是異步執行的。父類A能夠繼續執行直到B須要的時候。若是有必要,它能夠爲了同步等待讓步於B的引用。 

IEnumerator A()
{
    ...
     
    // Starts B as a coroutine and continues the execution
    Coroutine b = StartCoroutine( B() );
     
    ...
     
    // Waits for B to terminate
    yield return b;
     
    ...
}

 

若是你想要開始幾個並行協程的話這會很是有用,全部代碼在同一刻運行: 

IEnumerator A()
{
    ...
     
    // Starts B, C, and D as coroutines and continues the execution
    Coroutine b = StartCoroutine( B() );
    Coroutine c = StartCoroutine( C() );
    Coroutine d = StartCoroutine( D() );
     
    ...
     
    // Waits for B, C and D to terminate
    yield return b;
    yield return c;
    yield return d;
     
    ...
}

這種新模式容許任意數量的並行計算,當這些並行計算終止時恢復執行。

相關文章
相關標籤/搜索