87 lines
3.3 KiB
C#
87 lines
3.3 KiB
C#
using System.Reflection;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using PathBerserker2d;
|
||
|
||
namespace BaseGames.Editor
|
||
{
|
||
/// <summary>
|
||
/// 快捷键:BaseGames → Tools → Bake All NavSurfaces(Ctrl+Shift+B)
|
||
/// 烘焙当前场景中所有 PathBerserker2d NavSurface 的导航网格。
|
||
/// 等效于在每个 NavSurface Inspector 中逐一点击 "Bake"。
|
||
/// </summary>
|
||
public static class NavSurfaceBakeShortcut
|
||
{
|
||
// NavSurface.StartBakeJob() 和 NavSurface.BakeJob 均为 internal,通过反射访问。
|
||
private static readonly MethodInfo s_startBakeJobMethod =
|
||
typeof(NavSurface).GetMethod("StartBakeJob", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
private static readonly PropertyInfo s_bakeJobProp =
|
||
typeof(NavSurface).GetProperty("BakeJob", BindingFlags.NonPublic | BindingFlags.Instance);
|
||
|
||
[MenuItem("BaseGames/Tools/Bake All NavSurfaces %#b", priority = 100)]
|
||
public static void BakeAll()
|
||
{
|
||
var surfaces = Object.FindObjectsByType<NavSurface>(FindObjectsSortMode.None);
|
||
if (surfaces.Length == 0)
|
||
{
|
||
Debug.Log("[NavSurfaceBake] 当前场景没有找到 NavSurface 组件。");
|
||
return;
|
||
}
|
||
|
||
int count = 0;
|
||
foreach (var surface in surfaces)
|
||
{
|
||
if (surface == null) continue;
|
||
|
||
s_startBakeJobMethod?.Invoke(surface, null);
|
||
EditorApplication.update -= MakeWatcher(surface);
|
||
EditorApplication.update += MakeWatcher(surface);
|
||
count++;
|
||
}
|
||
|
||
Debug.Log($"[NavSurfaceBake] 开始烘焙 {count} 个 NavSurface……");
|
||
}
|
||
|
||
[MenuItem("BaseGames/Tools/Bake All NavSurfaces %#b", validate = true)]
|
||
private static bool BakeAllValidate()
|
||
{
|
||
// 仅在非 Play Mode 时可用(NavSurface.Bake 仅支持编辑器模式)
|
||
return !Application.isPlaying;
|
||
}
|
||
|
||
// ── 每个 NavSurface 独立监听烘焙完成 ──────────────────────────────
|
||
|
||
private static EditorApplication.CallbackFunction MakeWatcher(NavSurface surface)
|
||
{
|
||
EditorApplication.CallbackFunction watcher = null;
|
||
watcher = () =>
|
||
{
|
||
if (surface == null)
|
||
{
|
||
EditorApplication.update -= watcher;
|
||
return;
|
||
}
|
||
|
||
var bakeJob = s_bakeJobProp?.GetValue(surface);
|
||
if (bakeJob == null)
|
||
{
|
||
EditorApplication.update -= watcher;
|
||
return;
|
||
}
|
||
|
||
bool isFinished = (bool)bakeJob.GetType()
|
||
.GetProperty("IsFinished")!.GetValue(bakeJob);
|
||
if (isFinished)
|
||
{
|
||
EditorApplication.update -= watcher;
|
||
EditorUtility.SetDirty(surface);
|
||
float totalTime = (float)bakeJob.GetType()
|
||
.GetProperty("TotalBakeTime")!.GetValue(bakeJob);
|
||
Debug.Log($"[NavSurfaceBake] ✓ {surface.name} 烘焙完成({totalTime} ms)");
|
||
}
|
||
};
|
||
return watcher;
|
||
}
|
||
}
|
||
}
|