unity3D中使用協程來做“多次調用一次更新”特性的一個大坑。

來源:互聯網
上載者:User

有些事情一幀之內只需要做一次,比如收發郵件時,一幀內資料層多次的變化,表現層只需要一次更新。
我採用協程做這個事情,為了避免發起多個協程,我記錄了一個協程是否發起的變數。
但是u3d裡的coroutine,在發起的指令碼acvited=false後,就不更新了,並且我測試過,再恢複成actived = true,協程依舊不更新了,就像沒調用一樣。

以下是u3d關於協程的調用機制的解釋:

“在Unity3D中,使用MonoBehaviour.StartCoroutine方法即可開啟一個協同程式,也就是說該方法必須在MonoBehaviour或繼承於MonoBehaviour的類中調用。

       在Unity3D中,使用StartCoroutine(string methodName)和StartCoroutine(IEnumerator routine)都可以開啟一個線程。區別在於使用字串作為參數可以開啟線程並線上程結束前終止線程,相反使用IEnumerator 作為參數只能等待線程的結束而不能隨時終止(除非使用StopAllCoroutines()方法);另外使用字串作為參數時,開啟線程時最多隻能傳遞一個參數,並且效能消耗會更大一點,而使用IEnumerator
作為參數則沒有這個限制。

        在Unity3D中,使用StopCoroutine(string methodName)來終止一個協同程式,使用StopAllCoroutines()來終止所有可以終止的協同程式,但這兩個方法都只能終止該MonoBehaviour中的協同程式。

        還有一種方法可以終止協同程式,即將協同程式所在gameobject的active屬性設定為false,當再次設定active為ture時,協同程式並不會再開啟;如是將協同程式所在指令碼的enabled設定為false則不會生效。這是因為協同程式被開啟後作為一個線程在運行,而MonoBehaviour也是一個線程,他們成為互不干擾的模組,除非代碼中用調用,他們共同作用於同一個對象,只有當對象不可見才能同時終止這兩個線程。然而,為了管理我們額外開啟的線程,Unity3D將協同程式的調用放在了MonoBehaviour中,這樣我們在編程時就可以方便的調用指定指令碼中的協同程式,而不是無法去管理,特別是對於只根據方法名來判斷線程的方式在多人開發中很容易出錯,這樣的設計保證了對象、指令碼的條理化管理,並防止了重名。”

而我那些標誌還是【已經發起】狀態,這樣就發生死結了----想更新的發起不了,之前的異常結束導致標誌複位不了。

上述現象發生在使用者收到郵件後的一幀裡操作了滑鼠關閉了郵件系統。
由於網路訊息指派比使用者輸入的時機靠前(我們項目裡的既有結構),導致協程發起了,但實際無法執行。
如果先關閉,再處理資料,就會走關閉時的處理,就不會出錯了---可是網路訊息也是有可能導致UI關閉的,看商務邏輯了。

回到現狀,
我只能在隱藏的時候,恢複標誌。
可是u3d隱藏對象過於隨意,大多使用GameObject.SetActiveRecursively(bool)介面幹活。
這導致我無法保證所有處理該對象的代碼都知道恢複標誌這個事情。
我可以提煉一個特殊的Visible介面,確保標誌恢複,但是會有以下情況:
如果將邏輯分散到多個指令碼組件,如何訪問到這個特殊的Visible介面就會變得很麻煩。
如果這樣,那我還不如用Update來做。

目前的解決方案是:
一個場合恰好只有一個指令碼,能滿足“提煉一個特殊的Visible介面,確保標誌恢複”。
另外一個場合是很多指令碼,剛好協程只做可見度控制,這導致出錯了也不怕,因為會被其他可見度操作恢複。

 

誰能給出基於Coroutine的不會出死結問題的更新方案?

今天在好友名單的更新也用了協程。而且關閉邏輯剛好在別的指令碼裡,現在的打算是讓關閉按鈕捕獲使用者輸入後,轉給Model層,再分別通知各個指令碼組件執行恢複操作。

希望這麼做了,效率會比update效率高,反正我覺得這不是核心效能瓶頸。

 

zpbaaa 的方式正解~~多謝了。

在OnDisable的時候恢複即可,不用中轉了。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.