Files
zeling_v2/Assets/Scripts/Editor/NavSurfaceBakeShortcut.cs
2026-05-12 21:50:49 +08:00

87 lines
3.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.Reflection;
using UnityEditor;
using UnityEngine;
using PathBerserker2d;
namespace BaseGames.Editor
{
/// <summary>
/// 快捷键BaseGames → Tools → Bake All NavSurfacesCtrl+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;
}
}
}