淺談 Unity Coroutine 的運行方式

Ken-Yi Lee
Feis Studio
Published in
7 min readApr 20, 2019

--

從 Coroutine、await/async 到 C# job system,Unity 處理非同步工作有很多不同的方法。這次我們就先從在 Unity 內 Coroutine 是怎麼用單一執行緒執行的原理開始談起。

Unity 的 Coroutine 運作是建立在 MonoBehaviour 的行為之上,以單一執行緒 (thread) 的方式運行。所以在了解 Coroutine 的運行方式之前,我們先來看看 MonoBehaviour 的運行規則。

在每一幀畫面更新時,MonoBehaviour 會依照固定的順序進行可自定義的訊息 (message) 操作¹。如果我們只考慮到與 Coroutine 比較相關的部分,可以將進行流程表示成下圖這個樣子:

Unity MonoBehaviour 簡易運行流程

MonoBehaviour 的各種行為被固定而單一的執行順序串連在一起 (在上圖以箭頭表示),並根據目標幀率 (FPS) 在不同幀之間做必要的等待。使用時,如果每幀要進行的工作內容相似,則透過自定義 Update() 的方式實現即可。但如果是跨越多幀執行且具有進程的工作,就可以使用 Unity 的 Coroutine。

Unity 的 Coroutine 一般來說會在每幀更新的 Update() 後執行 :

大部分的 Coroutine 會在 Update() 結束後的 B 時間點執行

每幀更新到 B 時間點時,Unity 會將大部分已啟動但未結束的 Coroutine 逐一執行。每個 Coroutine 都會執行到 yield 述句或者函式結束為止。雖然跨越多幀的工作在感覺上是個連續的進程,但在 Unity 裡只是將工作切分成許多區段,在不同幀的影格裡執行而已:

Coroutine 會被切割在不同的影格執行

那要如何切割 Coroutine 呢?在 Coroutine 函式的每一個區段間,可以用 yield return null 中斷執行。Coroutine 用 yield return null 中斷執行後要等到下一幀同樣的 B 時間點才會接續執行:

--

--