天天看點

Unity 協程與線程

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t0">協程是不同步的</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t1">什麼是協程</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t2">Unity函數執行圖</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t3">簡單的協程示例</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t8">協程的實際用途</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t9">協程動畫示例</a>

<a href="http://www.cnblogs.com/zhaoqingqing/p/3750522.html#t10">資料</a>

協程 不是 線程,協同程式是 不同步 的

      一個線程在程式中和其他線程是異步運作的,在多處理器機器中一個線程可以同時與所有其他線程的實時運作其代碼,這使得線程程式設計能夠解決很複雜的事情,因為可能在相同的時間裡一個線程在改變它而另一個線程正在讀取它,這意味着另一個線程實際上可以改變的東西在遊戲中處理的中間似乎是你的源代碼一行。這是因為你寫的代碼是由機器變成彙編語言,更是更複雜。正因為如此,你必須通過鎖,以確定這種情況不會由任何確定沒有共享記憶體發生。或者通過鎖定其他線程使用同一塊記憶體,當他們在讀取或更改時。

      協同程式絕對不是一個線程。這意味着在同一時間隻有一個協同程式在執行,它會被執行在遊戲的主線程上,是以實際上在同一時間遊戲的核心隻有一個協同程式在運作[這段翻譯的不太準确]

     你永遠不需要擔心同步或鎖定一個值當你正在編寫一個協同程式。你有完全的控制權,直到你的代碼執行到 yiedld

  是以總結一下協程的定義

    協程隻是部分執行,并假定在适當的條件得到滿足,在未來的某一時刻将被恢複,直到它的工作完成

Unity processes coroutines every frame of the game for every object that has one or more running.  The processing occurs after Update and before LateUpdate for most yield statements, but there are special cases:

Unity的流程協同程式在遊戲的每一幀每個對象為具有一個或多個正在運作的。Update() 之後,LateUpdate()之前 ,發生的 yield 語句的處理,但也有特殊情況

Unity 協程與線程

When the coroutine is activated it will execute right up to the next yield statement and then it will pause until it is resumed.  You can see where it will resume in the diagram above, based on what you yield.

當協程被激活,它會一直到下一個 yield語句執行,然後它會暫停,直到它恢複。你可以在上圖中看到它會恢複,根據你的 yield語句。

讓我們來看看一個非常簡單的協程

該協程将會永遠執行下去。它記錄目前的時間,然後yield,當它被恢複,它又進入了這個循環,記錄一次時間,遇到 yield 并重複之前的操作

The code inside the loop is exactly like an Update function.  It runs once every frame for this object, just after the script's Update routine runs (if it has one).

這代碼循環就像 Update() 函數。這個對象在每一幀中運作,腳本的Update 程式運作後(如果有的話)

When you call StartCoroutine(TestCoroutine()) the code executes immediately up to the first time it yields, it will then be resumed when Unity processes coroutines for this object.

當你調用 StartCoroutine(TestCoroutine()) 代碼立即第一次得到執行 然後 yield,當Unity 引擎再次處理這個GameObject時,協程會被恢複

If you start a coroutine early in the processing of a game object, like creating one in Start, Update or OnCollisionEnter then that coroutine will immediately run up to the first yield, then it will resume during the same frame if you yield return null .

如果你在早于Unity處理到GameObject就執行一個協程 比如 Start(),Update()或OnCollisionEnter()将會繼續執行,當第一次遇到yield,然後同一幀會恢複,如果你yield null。有時候會有奇怪的結果,如果你不考慮它。

現在還有一件事,在我們的測試協程顯然不是無限循環

下列情況協程将會不再被執行:如果你撥打電話,會停止遊戲對象的協同程式,如果它被銷毀,它不會再次運作。如果腳本被直接或通過遊戲對象上使用SetActive(false),它也不會再執行。

Unity processes coroutines every frame of the game for every object that has one or more running.

Unity在處理協程時是 在遊戲的每一幀,每一個GameObject上進行的,可以處理1個或多個

你也許也想哦,不,它不需要,如果你使用這樣的

yield return new WaitForSeconds(1)then it doesn't process it for another 1 second!"那麼它不處理它的另外1秒Well actually Unity does process that coroutine every frame, checking to see if the right amount of time has elapsed - it doesn't process your code, but it does process the coroutine which is the wrapper its made around your script.那麼實際上,Unity 會處理協程在每一幀,檢查合适的時間是否已經過去,它不會處理你的代碼,但是它會處理這個協程,是你的腳本在包裝這個協程是以我們知道,我們可以有效的暫停我們的代碼通過 yield ,下面是那些你可以Return 的:

null -協程執行下一次,它是合格的

WaitForEndOfFrame - 協程的架構上執行,在所有的渲染和圖形使用者界面完成之後

WaitForFixedUpdate - 導緻此協程在下一次實體學的步驟執行,在所有的實體計算之後

WaitForSeconds - 使協程并不是一個特定的遊戲時間内執行

WWW - waits for a web request to complete (resumes as if WaitForSeconds or null)

Another coroutine - in which case the new coroutine will run to completion before the yielder is resumed(在這種情況下,新的協同程式将在這個Yield恢複之前完成)

You can also issue the command yield break; which immediately stops the coroutine.你還可以發出 yield break 指令,去立即停止這個協程Because of WaitForEndOfFrame coroutines can be used to get information from render textures when all cameras have completed rendering and the GUI has been displayed因為 WaitForEndOfFrame 協程可以用于從渲染紋理中擷取資訊, 當所有的Camera已完成渲染 并且 GUI 已經被顯示Using yield return new WaitForSeconds(x) will never resume if the Time.timeScale is set to 0.采用 yield return new WaitForSeconds(x) 将永遠不會被恢複,如果 Time.timeScale =0Of course the great thing about all of this is that you can write code that needs to execute over a period of time, or wait for some external event to occur, and keep it all nicely together in a single function making your code far more readable than if you had to write multiple functions or lots of code to keep checking the state of things.當然,關于這一切的偉大的事情是,你可以寫需要執行一段時間,或者等待發生一些外部事件,并保持它擁有時尚典雅的一起在一個單一的功能使你的代碼更易讀的代碼比,如果你不得不編寫多個函數的代碼或地段繼續檢查事物的狀态。這是真正的協同程式的地步。

Coroutines are a really good way of making a sequence of operations happen over time or when some external process is completed

Coroutines are not threads and are not asynchronous

Nothing else is running when your coroutine is executing

Your coroutine will resume when the conditions of your yield statement are met

Coroutines are inactive when the script is disabled or the object is destroyed

yield return new WaitForSeconds is dependent on game time which is affected by Time.timeScale

協程通過按順序的操作 或一些其實的處理 當它完成時

協程并不是線程,它沒有同步

沒有任何 或已經在運作協程

你的協程

希望我們已經了解了協程是什麼,以及它們在運作時。我們的進階教程将研究該技術在它們身後

讓我們用協程做一些事情。幾個簡單的輔助函數,使用協程可以讓我們建立易于切割的序列

我們可以寫一個協同的移動對象到目标位置和旋轉。我們可以寫一個協程的等待動畫是一個特定的完成百分比。然後利用這兩個工具, 我們可以很容易地編寫腳本在一個單一的功能,其中它會很容易閱讀全切序列

使用協程,通過觀看它在移動,為的是要確定不會有其它的協程或Update()函數裡更改它的位置在同一時間確定你隻有一個協程影響GameObject在同一時間,禁用Update() 函數 移動對象

這裡有一個協同的一個例子等待動畫部分完成

You could write a coroutine to wait for an animation like this:

本文轉自趙青青部落格園部落格,原文連結:http://www.cnblogs.com/zhaoqingqing/p/3750522.html,如需轉載請自行聯系原作者

繼續閱讀