File directory changes (mirror Scripts/ module structure): - AbilityTypeDrawer.cs → Equipment/ - CharacterWizardWindow.cs → Character/ - FormEditorWindow.cs → Player/ - GMToolWindow.cs → Tools/ - SOManagerWindow.cs → Tools/ - Map/MapRoomDataEditor.cs → World/Map/ - Navigation/ (root) → Enemies/Navigation/ - Achievements/ → Progression/ Menu hierarchy changes (BaseGames/ top-level): - Data/: +Character Wizard (from Tools/), +Boss Skill Sequence (from Tools/) - Addressables/: +Addressable Batch Tool, +Asset Reference Graph, +Validate Address Keys (from Tools/Verification/) - Scene/Setup/: +Boot Flow Wizard, +Scaffold *, +Auto-Open Persistent (from Tools/) - Scene/: +Camera Area Setup (from Camera/), +Bake All NavSurfaces (from Tools/) - Events/: +Event Bus Monitor, +Event Chain Viewer, +Create/Reimport Event Channels (from Tools/) - Tools/Validation/: +Validate All SOs, +Apply/Validate Script Order (from Tools/ flat) - Tools/Maintenance/: +Missing Scripts/*, +Physics2D Layer Matrix/* (from Tools/ flat) Result: BaseGames/Tools/ reduced from 16 flat items to 4 items + 2 submenus Docs: update AssetFolderSpec §12 editor tool table with new menu paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
79 lines
2.9 KiB
C#
79 lines
2.9 KiB
C#
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UnityEditor;
|
||
using UnityEditor.Build;
|
||
using UnityEditor.Build.Reporting;
|
||
using UnityEngine;
|
||
|
||
namespace BaseGames.Editor
|
||
{
|
||
/// <summary>
|
||
/// 扫描项目中所有实现 <see cref="BaseGames.Core.IValidatable"/> 接口的 ScriptableObject,
|
||
/// 调用 Validate() 并在 Console 报告验证结果。同时作为构建前处理器,发现错误时中止构建。
|
||
///
|
||
/// 菜单:BaseGames/Tools/Validate All ScriptableObjects
|
||
/// Build 回调顺序 = 1(在 AddressKeyValidator callbackOrder = 0 之后执行)
|
||
/// </summary>
|
||
public class SOValidationRunner : IPreprocessBuildWithReport
|
||
{
|
||
public int callbackOrder => 1;
|
||
|
||
public void OnPreprocessBuild(BuildReport report)
|
||
{
|
||
var (errors, warnings) = RunAll();
|
||
|
||
foreach (var w in warnings)
|
||
Debug.LogWarning(w);
|
||
|
||
if (errors.Count > 0)
|
||
throw new BuildFailedException(
|
||
$"[SOValidationRunner] {errors.Count} 处 SO 数据错误,构建中止:\n"
|
||
+ string.Join("\n", errors));
|
||
}
|
||
|
||
[MenuItem("BaseGames/Tools/Validation/Validate All ScriptableObjects")]
|
||
public static void ValidateMenu()
|
||
{
|
||
var (errors, warnings) = RunAll();
|
||
|
||
if (errors.Count == 0 && warnings.Count == 0)
|
||
{
|
||
Debug.Log("[SOValidationRunner] ✅ 所有 SO 数据均合法。");
|
||
return;
|
||
}
|
||
|
||
foreach (var w in warnings) Debug.LogWarning(w);
|
||
foreach (var e in errors) Debug.LogError(e);
|
||
|
||
Debug.Log($"[SOValidationRunner] 校验完成:{errors.Count} 错误,{warnings.Count} 警告。");
|
||
}
|
||
|
||
// ── Internal ──────────────────────────────────────────────────────
|
||
|
||
private static (List<string> errors, List<string> warnings) RunAll()
|
||
{
|
||
var errors = new List<string>();
|
||
var warnings = new List<string>();
|
||
|
||
var guids = AssetDatabase.FindAssets("t:ScriptableObject");
|
||
foreach (var guid in guids)
|
||
{
|
||
var path = AssetDatabase.GUIDToAssetPath(guid);
|
||
var so = AssetDatabase.LoadAssetAtPath<ScriptableObject>(path);
|
||
if (so is BaseGames.Core.IValidatable validatable)
|
||
{
|
||
foreach (var result in validatable.Validate())
|
||
{
|
||
if (result.Severity == BaseGames.Core.ValidationSeverity.Error)
|
||
errors.Add($"❌ {result.Message} ({path})");
|
||
else
|
||
warnings.Add($"⚠️ {result.Message} ({path})");
|
||
}
|
||
}
|
||
}
|
||
|
||
return (errors, warnings);
|
||
}
|
||
}
|
||
}
|