在我们使用Unity编辑器扩展做一些批处理的工具时,通常会需要显示一个进度条,这样不会让Unity一直卡住不动,使得使用者不知道当前的进展。
那么如何显示进度条呢?涉及的相关API有:
EditorUtility.ClearProgressBar();
https://docs.unity3d.com/cn/2018.4/ScriptReference/EditorUtility.ClearProgressBar.html
带取消按钮的进度条
EditorUtility.DisplayCancelableProgressBar
https://docs.unity3d.com/cn/2018.4/ScriptReference/EditorUtility.DisplayCancelableProgressBar.html
不带取消按钮的进度条
EditorUtility.DisplayProgressBar
https://docs.unity3d.com/cn/current/ScriptReference/EditorUtility.DisplayProgressBar.html
一般使用我们都会使用带取消按钮的进度条去完成工具的编写,这样可交互性更强。
提供一个通用的进度条相关的类和方法:
using System;
using UnityEditor;
using UnityEngine;
namespace EditorHelp
{
/// <summary>
/// 编辑器辅助工具类
/// </summary>
public static class EditorUtilityHelp
{
private static void ClearUpdate(EditorApplication.CallbackFunction func)
{
EditorUtility.ClearProgressBar();
if (func == null) return;
EditorApplication.update -= func;
}
/// <summary>
/// 显示操作进度
/// </summary>
/// <param name="title">标题</param>
/// <param name="length">操作内容长度</param>
/// <param name="onUpdate">逐个操作响应</param>
/// <param name="onComplete">操作结束回调</param>
public static EditorApplication.CallbackFunction ShowUpdate(string title, int length, Action<int> onUpdate,
Action onComplete = null)
{
string[] tips = new string[length];
for (int i = 0; i < tips.Length; i++)
{
tips[i] = "";
}
return ShowUpdate(title, tips, onUpdate, onComplete);
}
/// <summary>
/// 显示操作进度
/// </summary>
/// <param name="title">标题</param>
/// <param name="tips">操作提示数组</param>
/// <param name="onUpdate">逐个操作响应</param>
/// <param name="onComplete">操作结束回调</param>
private static EditorApplication.CallbackFunction ShowUpdate(string title, object[] tips, Action<int> onUpdate,
Action onComplete = null)
{
if (tips.Length == 0)
{
onComplete?.Invoke();
return null;
}
int index = 0;
EditorApplication.CallbackFunction func = null;
func = () =>
{
string titleStr = $@"{title} [{index}/{tips.Length}]";
bool isCancel = EditorUtility.DisplayCancelableProgressBar(titleStr, tips[index].ToString(),
(float) index / tips.Length);
try
{
onUpdate(index);
}
catch (Exception e)
{
Debug.LogErrorFormat(@"【 {0} | {1} 】 {2}", title, tips[index], e);
ClearUpdate(func);
index = 0;
}
index++;
if (isCancel)
{
ClearUpdate(func);
index = 0;
}
else if (index >= tips.Length)
{
ClearUpdate(func);
index = 0;
onComplete?.Invoke();
}
};
EditorApplication.update += func;
return func;
}
}
}
|