您的位置:首页 > 移动开发 > Unity3D

Unity如何在Editor下执行协程(coroutine)

2016-03-01 20:19 477 查看
在处理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。这个我并没有实际验证。

文章转载自Unity如何在Editor下执行协程(coroutine),感谢原作者提供好文章
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: