在处理Unity5新的AssetBundle的时候,我有一个需求,需要在Editor下(比如一个menuitem的处理函数中,游戏没有运行,也没有MonoBehaviour)加载AssetBundle。而加载AssetBundle的时候又需要使用yield return www;这样的协程用法。
所以就有了一个需求,在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; } } }
这里需要注意几个地方:
1、EditorApplication.update,这个是一个delegate,可以绑定一个函数,从而在编辑器下执行Update。
2、EditorCoroutineRunner.StartEditorCoroutine(Routine1()); 这样可以在编辑器下开启一个协程。
3、另外一个思路是不使用协程,绑定一个Update函数,然后判断www.isDone来获取AssetBundle。这个我并没有实际验证。
时间: 2024-10-11 11:44:27