Unity - 在编辑模式正确运行Coroutines.
环境:
Unity2019.4, Windows 10
问题:
在编辑模式下,某些Coroutine可以正确运行,但是如果IEnumerator中含有while或for循环,那么Coroutine会卡在循环中,此时只有手动更新Editor(例如在Inspector中输入,或在Scene中移动某个GameObject),Coroutine才会继续迭代。
推测原因:
IEnumerator所依赖的某些刷新机制在Edit Mode下没有被自动执行。
解决:
在Monobehaviour或Editor类中使用EditorApplication.update callback 配合EditorApplication.QueuePlayerLoopUpdate 强制更新。
实现:
MonoBehaviour version:
[ExecuteInEditMode]
public class EditModeUpdateHandler : MonoBehaviour
{
...
void OnEnable()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.update += ConstantLoopUpdate;
#endif
}
#if UNITY_EDITOR
void ConstantLoopUpdate()
{
if (!Application.isPlaying) {
//在此加入其它判定条件.Add other condition statements here.
UnityEditor.EditorApplication.QueuePlayerLoopUpdate();
Debug.Log("Loop Updated from " + this.name);
}
}
#endif
...
}
或者采用Editor version:
...
using UnityEditor;
public class LoopUpdateEditor : Editor
{
void OnEnable()
{
EditorApplication.update += ConstantLoopUpdate;
}
void ConstantLoopUpdate()
{
if (!Application.isPlaying) {
//在此加入其他判定条件.Add other condition statements here.
EditorApplication.QueuePlayerLoopUpdate();
Debug.Log("Loop Updated from Editor!");
}
}
...
}
总结:
此方法可以在没有进入Play模式的情况下正常运行MonoBehaviour.StartCoroutine(),即使IEnumerator中含有while或for循环,即便在Unity Editor处于后台时也可运行。
推论:
1.Coroutine底层其实仍依赖Update()方法;
2.带有[ExecuteInEditMode] Attribute的MonoBehaviour中的Update()函数,只有在Scene更新或EditorGUI更新时才会执行;
3.在非Play模式下,UnityEditor.EditorApplication.update 效果等同于Play模式下的MonoBehaviour.Update()
4.UnityEditor.EditorApplication.QueuePlayerLoopUpdate()会调用所有带有[ExecuteInEditMode] Attribuete 或runInEditMode = true 的MonoBehaviour.Update()
参考: