做者ChevyRay ,2013年9月28日,snaker7譯 原文地址:http://unitypatterns.com/introduction-to-coroutines/html 在Unity中,協程(Coroutines)的形式是我最喜歡的功能之一,幾乎在全部的項目中,我都會使用它來控制運動,序列,以及對象的行爲。在這個教程中,我將會說明協程是如何工做的,而且會附上一些例子來介紹它的用法。程序員
協程介紹數組
Unity的協程系統是基於C#的一個簡單而強大的接口 ,IEnumerator,它容許你爲本身的集合類型編寫枚舉器。這一點你沒必要關注太多,咱們直接進入一個簡單的例子來看看協程到底能幹什麼。首先,咱們來看一下這段簡單的代碼...多線程
倒計時器app 這是一個簡單的腳本組件,只作了倒計時,而且在到達0的時候log一個信息。函數
還不錯,代碼簡短實用,但問題是,若是咱們須要複雜的腳本組件(像一個角色或者敵人的類),擁有多個計時器呢?剛開始的時候,咱們的代碼也許會是這樣的:工具
儘管不是太糟糕,可是我我的不是很喜歡本身的代碼中充斥着這些計時器變量,它們看上去很亂,並且當我須要從新開始計時的時候還得記得去重置它們(這活我常常忘記作)。oop
若是我只用一個for循環來作這些,看上去是否會好不少?post
如今每個計時器變量都成爲for循環的一部分了,這看上去好多了,並且我不須要去單獨設置每個跌倒變量。學習
好的,你可能如今明白個人意思:協程能夠作的正是這一點!
碼入你的協程! 如今,這裏提供了上面例子運用協程的版本!我建議你從這裏開始跟着我來寫一個簡單的腳本組件,這樣你能夠在你本身的程序中看到它是如何工做的。
這看上去有點不同,不要緊,接下來我會解釋這裏到底發生了什麼。
這一行用來開始咱們的Countdown程序,注意,我並無給它傳入參數,可是這個方法調用了它本身(這是經過傳遞Countdown的return返回值來實現的)。
Yield 在Countdown方法中其餘的都很好理解,除了兩個部分: l IEnumerator 的返回值 l For循環中的yield return
爲了能在連續的多幀中(在這個例子中,3秒鐘等同於不少幀)調用該方法,Unity必須經過某種方式來存儲這個方法的狀態,這是經過IEnumerator 中使用yield return語句獲得的返回值,當你「yield」一個方法時,你至關於說了,「如今中止這個方法,而後在下一幀中從這裏從新開始!」。
注意:用0或者null來yield的意思是告訴協程等待下一幀,直到繼續執行爲止。固然,一樣的你能夠繼續yield其餘協程,我會在下一個教程中講到這些。
一些例子 協程在剛開始接觸的時候是很是難以理解的,不管是新手仍是經驗豐富的程序員我都見過他們對於協程語句束手無策的時候。所以我認爲經過例子來理解它是最好的方法,這裏有一些簡單的協程例子:
屢次輸出「Hello」 記住,yield return是「中止執行方法,而且在下一幀從這裏從新開始」,這意味着你能夠這樣作:
每一幀輸出「Hello」,無限循環。。。 經過在一個while循環中使用yield,你能夠獲得一個無限循環的協程,這幾乎就跟一個Update()循環等同。。。
計時 ...不過跟Update()不同的是,你能夠在協程中作一些更有趣的事:
這個方法突出了協程一個很是酷的地方:方法的狀態被存儲了,這使得方法中定義的這些變量都會保存它們的值,即便是在不一樣的幀中。還記得這個教程開始時那些煩人的計時器變量嗎?經過協程,咱們不再須要擔憂它們了,只須要把變量直接放到方法裏面!
開始和終止協程 以前,咱們已經學過了經過 StartCoroutine()方法來開始一個協程,就像這樣:
若是咱們想要終止全部的協程,能夠經過StopAllCoroutines()方法來實現,它的所要作的就跟它的名字所表達的同樣。注意,這隻會終止在調用該方法的對象中(應該是指調用這個方法的類吧)開始的協程,對於其餘的MonoBehavior類中運行的協程不起做用。
若是咱們有如下這樣兩條協程語句:
。。。那咱們怎麼終止其中的一個協程呢?在這個例子裏,這是不可能的,若是你想要終止某一個特定的協程,那麼你必須得在開始協程的時候將它的方法名做爲字符串,就像這樣:
更多關於協程的學習 即將爲你帶來:「Scripting with Coroutines」,一個更深刻的介紹,關於如何使用協程以及如何經過協程編寫對象行爲。
擴展連接 l Coroutines – Unity Script Reference 若是你知道其餘很棒的關於協程的Unity教程,或者相關的主題,請在回覆中分享連接!固然,若是在教程有什麼問題,好比連接無效或者其餘一些問題,歡迎給我發郵件。 |
做者ChevyRay ,2013年9月28日,snaker7譯 原文地址:http://unitypatterns.com/scripting-with-coroutines/
請注意:這個關於協程的教程共有兩部分,這是第二部分,若是您不曾看過第一部分——協程介紹,那麼在閱讀這部份內容以前建議您先了解一下。
計時器例子
在第一個教程中,咱們已經瞭解了協程如何讓一個方法「暫停」下來,而且讓它yield直到某些值到達咱們給定的數值;而且利用它,咱們還建立了一個很棒的計時器系統。協程一個很重要的內容是,它可讓普通的程序(比方說一個計時器)很容易地被抽象化而且被複用。
協程的參數
抽象化一個協程的第一個方法是給它傳遞參數,協程做爲一個函數方法來講,它天然可以傳遞參數。這裏有一個協程的例子,它在特定的地方輸出了特定的信息。
嵌套的協程
在此以前,咱們yield的時候老是用0(或者null),僅僅告訴程序在繼續執行前等待下一幀。協程最強大的一個功能就是它們能夠經過使用yield語句來相互嵌套。
眼見爲實,咱們先來建立一個簡單的Wait()程序,不須要它作任何事,只須要在運行的時候等待一段時間就結束。
接下來咱們要編寫另外一個協程,以下:
第二個方法用了yield,但它並無用0或者null,而是用了Wait()來yield,這至關因而說,「再也不繼續執行本程序,直到Wait程序結束」。
如今,協程在程序設計方面的能力要開始展示了。
控制對象行爲的例子
在最後一個例子中,咱們就來看看協程如何像建立方便的計時器同樣來控制對象行爲。協程不只僅可使用可計數的時間來yield,它還能很巧妙地利用任何條件。將它與嵌套結合使用,你會獲得控制遊戲對象狀態的最強大工具。
運動到某一位置
對於下面這個簡單腳本組件,咱們能夠在Inspector面板中給targetPosition和moveSpeed變量賦值,程序運行的時候,該對象就會在協程的做用下,以咱們給定的速度運動到給定的位置。
這樣,這個程序並無經過一個計時器或者無限循環,而是根據對象是否到達指定位置來yield。
按指定路徑前進
咱們可讓運動到某一位置的程序作更多,不只僅是一個指定位置,咱們還能夠經過數組來給它賦值更多的位置,經過MoveToPosition() ,咱們可讓它在這些點之間持續運動。
我還加了一個布爾變量,你能夠控制在對象運動到最後一個點時是否要進行循環。
把Wait()程序加進來,這樣就能讓咱們的對象在某個點就能夠選擇是否暫停下來,就像一個正在巡邏的AI守衛同樣,這真是錦上添花啊!
注意:
若是你剛接觸協程,我但願這兩個教程能幫助你瞭解它們是如何工做的,以及如何來使用它們。如下是一些在使用協程時須謹記的其餘注意事項:
若是您發現教程中存在問題和錯誤的信息,或者有任何建議又或者您想要在這裏看到其餘須要的教程,能夠發郵件或者在評論中留言。