在處理Unity5新的AssetBundle的時候,我有一個需求,需要在Editor下(比方一個menuitem的處理函數中,遊戲沒有執行。也沒有MonoBehaviour)載入AssetBundle。而載入AssetBundle的時候又需要使用yield return www;這種協程使用方法。app
因此就有了一個需求,在Editor下運行協程。我從網上找到一個EditorCoroutine。其代碼例如如下:編輯器
using UnityEngine; using UnityEditor; using System.Collections; using System.Collections.Generic; using System.Runtime.CompilerServices; public static class EditorCoroutineRunner { private class EditorCoroutine : IEnumerator { private Stack<IEnumerator> executionStack; public EditorCoroutine(IEnumerator iterator) { this.executionStack = new Stack<IEnumerator>(); this.executionStack.Push(iterator); } public bool MoveNext() { IEnumerator i = this.executionStack.Peek(); if (i.MoveNext()) { object result = i.Current; if (result != null && result is IEnumerator) { this.executionStack.Push((IEnumerator)result); } return true; } else { if (this.executionStack.Count > 1) { this.executionStack.Pop(); return true; } } return false; } public void Reset() { throw new System.NotSupportedException("This Operation Is Not Supported."); } public object Current { get { return this.executionStack.Peek().Current; } } public bool Find(IEnumerator iterator) { return this.executionStack.Contains(iterator); } } private static List<EditorCoroutine> editorCoroutineList; private static List<IEnumerator> buffer; public static IEnumerator StartEditorCoroutine(IEnumerator iterator) { if (editorCoroutineList == null) { // test editorCoroutineList = new List<EditorCoroutine>(); } if (buffer == null) { buffer = new List<IEnumerator>(); } if (editorCoroutineList.Count == 0) { EditorApplication.update += Update; } // add iterator to buffer first buffer.Add(iterator); return iterator; } private static bool Find(IEnumerator iterator) { // If this iterator is already added // Then ignore it this time foreach (EditorCoroutine editorCoroutine in editorCoroutineList) { if (editorCoroutine.Find(iterator)) { return true; } } return false; } private static void Update() { // EditorCoroutine execution may append new iterators to buffer // Therefore we should run EditorCoroutine first editorCoroutineList.RemoveAll ( coroutine => { return coroutine.MoveNext() == false; } ); // If we have iterators in buffer if (buffer.Count > 0) { foreach (IEnumerator iterator in buffer) { // If this iterators not exists if (!Find(iterator)) { // Added this as new EditorCoroutine editorCoroutineList.Add(new EditorCoroutine(iterator)); } } // Clear buffer buffer.Clear(); } // If we have no running EditorCoroutine // Stop calling update anymore if (editorCoroutineList.Count == 0) { EditorApplication.update -= Update; } } }
一、EditorApplication.update,這個是一個delegate,可以綁定一個函數,從而在編輯器下運行Update。函數
二、EditorCoroutineRunner.StartEditorCoroutine(Routine1()); 這樣可以在編輯器下開啓一個協程。ui
三、另一個思路是不使用協程,綁定一個Update函數,而後推斷www.isDone來獲取AssetBundle。this
這個我並無實際驗證。spa
四、www可以正常的載入出AssetBundle。但是isDone的變量一直爲false。額外要注意因爲Editor模式下不存在退出遊戲清理資源的概念,因此要注意處理已載入的assetbundle的狀況,不然可能會報衝突的錯誤。code
五、理論上僅僅支持yield return null這種狀況,延時要本身處理。協程
Unity協程的原理是引擎在特定條件下運行MoveNext運行如下的語句。在上面的代碼中不管是延時仍是其它的東西,都是每幀運行MoveNext,這樣WaitForSeconds這種協程是無效的。blog
www的狀況比較特殊,儘管理論上也是會有問題的。但是確實可以正常的取到結果。遊戲