# 09 · 编辑器扩展 > **命名空间** `BaseGames.Editor` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **程序集** `BaseGames.Editor.asmdef`(Editor-only,不打包进 Runtime) --- ## 目录 1. [设计原则](#1-设计原则) 2. [自定义 Inspector 列表](#2-自定义-inspector-列表) 3. [EditorWindow 工具列表](#3-editorwindow-工具列表) 4. [Scene 视图 Gizmos 汇总](#4-scene-视图-gizmos-汇总) 5. [Play Mode 调试叠加层](#5-play-mode-调试叠加层) 6. [ContextMenu 工具](#6-contextmenu-工具) 7. [编辑器菜单结构](#7-编辑器菜单结构) 8. [自动化检查工具](#8-自动化检查工具) 9. [高级工具集(补充)](#9-高级工具集补充) --- ## 1. 设计原则 - **编辑器扩展与运行时代码完全分离**:所有编辑器扩展代码置于 `Editor/` 文件夹,使用独立 `.asmdef` - **工具服务于制作流程**:每个工具针对具体的制作痛点,不做泛用性过度设计 - **视觉化优先**:Gizmos 和自定义 Inspector 的目标是"**看一眼就知道配置是否正确**" - **不破坏运行时行为**:所有 Inspector 修改通过 `SerializedObject.ApplyModifiedProperties()` 标准流程,支持撤销(Undo) - **UI 技术选型**:所有编辑器扩展统一使用 **Unity UI Toolkit(UIElements)**,不使用 IMGUI(`OnGUI` / `EditorGUILayout`) ### UI Toolkit 统一规范 **自定义 Inspector** — 使用 `CreateInspectorGUI()` + `BindProperty()`: ```csharp [CustomEditor(typeof(PlayerController))] public class PlayerControllerEditor : Editor { public override VisualElement CreateInspectorGUI() { var root = new VisualElement(); // 默认字段绑定(替代 DrawDefaultInspector) InspectorElement.FillDefaultInspector(root, serializedObject, this); // 自定义运行时状态区 var statusFoldout = new Foldout { text = "运行时状态(Play Mode)" }; var stateLabel = new Label(); stateLabel.schedule.Execute(() => { if (!EditorApplication.isPlaying) return; var t = target as PlayerController; stateLabel.text = $"State: {t.CurrentStateName} HP: {t.HP}/{t.MaxHP}"; }).Every(100); // 100ms 轮询 statusFoldout.Add(stateLabel); // 调试按钮(Play Mode only) var debugGroup = new VisualElement(); debugGroup.SetEnabled(false); EditorApplication.playModeStateChanged += state => debugGroup.SetEnabled(state == PlayModeStateChange.EnteredPlayMode); var hurtBtn = new Button(() => (target as PlayerController)?.TakeDamage(2)) { text = "Hurt 2" }; debugGroup.Add(hurtBtn); root.Add(statusFoldout); root.Add(debugGroup); return root; } } ``` **EditorWindow** — 使用 `CreateGUI()` + 内置控件: ```csharp public class MyTool : EditorWindow { [MenuItem("BaseGames/My Tool")] public static void Open() => GetWindow("My Tool"); public void CreateGUI() { var splitView = new TwoPaneSplitView(0, 260f, TwoPaneSplitViewOrientation.Horizontal); var left = new ScrollView(); var right = new VisualElement(); splitView.Add(left); splitView.Add(right); rootVisualElement.Add(splitView); } } ``` **§2–§9 各工具使用的关键 UI Toolkit 控件**: | 工具 | 关键控件 | 说明 | |------|---------|------| | §2.x 自定义 Inspector | `ProgressBar`、`Foldout`、`Button`、`Label` | `CreateInspectorGUI()` 替代 `OnInspectorGUI()` | | §2.3 ParrySystem(时间轴)| 自绘 `VisualElement`(`generateVisualContent` + `Painter2D`)| 替代 `GUI.Box` 手绘条 | | §3.1–3.4 简单 EditorWindow | `ListView`、`Button`、`TextField` | `CreateGUI()` 替代 `OnGUI()` | | §9.1 BT 验证器 | `TreeView` | 原生树形控件 | | §9.2 进程流程图 | `GraphView`(`UnityEditor.Experimental.GraphView`)| 节点图;见注意事项 | | §9.3 GameState 分析器 | `MultiColumnListView` | 矩阵视图 | | §9.4 伤害模拟器 | `TwoPaneSplitView` + 自绘直方图(`Painter2D`)| 参数面板 + 分布图 | | §9.7 装备预览 | `TwoPaneSplitView` + `DropdownField` | 响应式分栏 | | §9.8 构建验证器 | `MultiColumnListView` + 可点击 `Label` | 多列结果 + 跳转 | > **GraphView 注意**:`UnityEditor.Experimental.GraphView` 标注为 Experimental,API 可能在 Unity 版本间变动。如遇稳定性问题,9.2 进程流程图可改为 `VisualElement` 手绘节点(`generateVisualContent` + `Painter2D.DrawBezierCurve`),无需依赖 Experimental API。 **USS 样式文件存放**:`Assets/Editor/UI/USS/` — 统一样式变量(颜色、间距、字体大小),通过 `styleSheets.Add()` 挂载。 --- ## 2. 自定义 Inspector 列表 ### 2.1 PlayerController Inspector **目标**:Play Mode 下直观监控玩家状态,快速触发测试。 **布局规划**: ``` ┌─ PlayerController ─────────────────────────────────┐ │ ◈ 状态信息 │ │ ┌──────────────────────────────────────────────┐ │ │ │ Current State RunState │ │ │ │ HP ████████████░░ 8 / 10 │ │ │ │ Soul ███████░░░░░░░ 66 / 99 │ │ │ │ Geo 340 │ │ │ │ IsGrounded ✓ FacingDir → (+1) │ │ │ │ Invincible ░░░░░░░░░░ (0.00s remaining) │ │ │ └──────────────────────────────────────────────┘ │ │ ◈ 已解锁能力 │ │ ┌──────────────────────────────────────────────┐ │ │ │ [✓ Parry] [✓ DoubleJump] [✗ WallJump] │ │ │ │ [✗ AerialDash] [✗ Swim] │ │ │ └──────────────────────────────────────────────┘ │ │ ◈ 调试工具(Play Mode Only) │ │ [Force Idle] [Force Run] [Force Air] │ │ [Deal Damage: 2] [Deal Damage: 10] [Instant Kill] │ │ [Add Soul: 33] [Add Geo: 100] │ │ [Unlock All Abilities] [Lock All Abilities] │ └────────────────────────────────────────────────────┘ ``` **实现方式**:继承 `Editor`,重写 `CreateInspectorGUI()` 返回 `VisualElement` 树。进度条使用 UI Toolkit `ProgressBar` 控件;Play Mode 限定区域通过 `debugGroup.SetEnabled(EditorApplication.isPlaying)` + `EditorApplication.playModeStateChanged` 回调控制显隐。 --- ### 2.2 EnemyBase Inspector **目标**:快速查看敌人 AI 状态,测试战斗参数。 ``` ┌─ EnemyBase ──────────────────────────────────────┐ │ ◈ 运行时状态(Play Mode) │ │ State: Controlled HP: █████████░ 90/100 │ │ BD Node: BD_MoveToPlayer (Running) │ │ Nav Status: Moving → (12.5, -3.0) [0.8m left] │ │ ◈ 属性配置 │ │ Stats SO: [ES_GruntWarrior ▼] │ │ AnimCfg : [EA_GruntWarrior ▼] │ │ ◈ 调试工具(Play Mode Only) │ │ [Force Stagger] [Force Death] [Reset HP] │ │ [Disable BD] [Enable BD] [Reload BD Tree] │ └──────────────────────────────────────────────────┘ ``` --- ### 2.3 ParrySystem Inspector **目标**:可视化弹反时间轴,测试弹反参数。 ``` ┌─ ParrySystem ────────────────────────────────────┐ │ ◈ 时间轴预览 │ │ [▌ Startup ▌▌▌▌▌▌▌ Active Window ▌▌ Endlag ▌] │ │ 0.05s 0.28s 0.10s │ │ ◈ 运行时状态(Play Mode) │ │ State: Active Timer: 0.19s / 0.28s │ │ Window: ████████████░░░ 68% │ │ CounterW: ────────────── (Inactive) │ │ ◈ 调试工具 │ │ [Trigger Parry Success] [Trigger Parry Fail] │ │ [Open Counter Window] [Reset] │ └──────────────────────────────────────────────────┘ ``` **时间轴预览** 在 Edit Mode 下也可显示(根据 `ParryConfigSO` 参数计算比例),方便策划调整数值时直观预览窗口比例。 --- ### 2.4 RoomCameraBounds Inspector **目标**:防止镜头边界配置错误。 ``` ┌─ RoomCameraBounds ───────────────────────────────┐ │ ◈ 边界检查 │ │ Bounds Size: (32.0, 18.0) │ │ Camera View (4.22 OrthoSize): (29.9, 16.8) │ │ Status: ✓ 边界大于镜头视野 │ │ ─────────────────────────────────────────────── │ │ [Preview Camera View in Scene] │ │ [自动调整 PolygonCollider2D 至最小安全尺寸] │ └──────────────────────────────────────────────────┘ ``` --- ### 2.5 DamageSourceSO Inspector **目标**:策划配置攻击参数时,即时预览伤害计算和属性。 ``` ┌─ DamageSourceSO ─────────────────────────────────┐ │ ◈ 伤害预览 │ │ BaseDamage × Multiplier = Final │ │ 5 × 1.0 = 5 │ │ ◈ 击退预览 │ │ KnockbackForce: 8.0 Direction: → │ │ HitStun: 0.30s │ │ ◈ 属性标记 │ │ [CanBeParried ✓] [Unblockable ✗] [IgnoreIFrame ✗]│ │ ◈ 伤害类型 │ │ Type: Normal (物理) │ │ HitFxType: Slash │ └──────────────────────────────────────────────────┘ ``` --- ## 3. EditorWindow 工具列表 ### 3.1 房间连接验证工具 **菜单路径**:`BaseGames > World > Room Connection Validator` **功能**: ``` ┌─ Room Connection Validator ──────────────────────────────────────┐ │ 扫描所有 Room_*.unity 场景中的 RoomTransition 组件 │ │ │ │ 房间 出口ID 目标场景 │ │ ────────────────────────────────────────────────────────────── │ │ Room_Forest_01 Door_To_Forest_02 ✓ Room_Forest_02 存在 │ │ Room_Forest_02 Door_To_Cave_01 ✓ Room_Cave_01 存在 │ │ Room_Cave_01 Door_To_Boss ✗ Boss_Cave 不存在 ⚠ │ │ │ │ SpawnPoint 检查: │ │ Room_Forest_02 缺少 SpawnPoint "SP_From_Forest_01_Door" ⚠ │ │ │ │ [重新扫描] [选中有错误的场景] [导出验证报告.md] │ └──────────────────────────────────────────────────────────────────┘ ``` --- ### 3.2 SO 事件频道监视器 **菜单路径**:`BaseGames > Core > Event Channel Monitor` **功能**:Play Mode 下实时监听所有 SO 事件频道的触发情况。 ``` ┌─ Event Channel Monitor ──────────────────────────────────────────┐ │ [▶ Play Mode Only] [清除日志] [暂停记录] │ │ │ │ 时间 事件频道 数据 │ │ ────────────────────────────────────────────────────────────── │ │ 0.012s OnPlayerHPChanged value: 8 │ │ 0.013s OnHitConfirmed DMG:5, Knockback:8.0 │ │ 1.245s OnParrySuccess DMG:5, Flags: CanBeParried │ │ 1.248s OnPlayerHPChanged value: 8 (no change) │ │ 2.001s OnRoomEntered Transform: Room_Forest_01 │ │ │ │ [筛选频道: ___________] [仅显示Player] [仅显示Combat] │ └──────────────────────────────────────────────────────────────────┘ ``` --- ### 3.3 NavSurface 快速烘焙工具 **菜单路径**:`BaseGames > Navigation > Quick Bake All Rooms` 一键遍历所有场景中的 `NavSurface`,按顺序烘焙 PathBerserker2d 导航网格并保存场景: ``` ┌─ NavSurface Bake Tool ──────────────────────────────────────────┐ │ 扫描到 NavSurface 数量: 12 │ │ │ │ Room_Forest_01: ✓ 已烘焙 (2024-01-01 12:00) │ │ Room_Forest_02: ⚠ 需要重新烘焙(场景已修改) │ │ Room_Cave_01: ✓ 已烘焙 │ │ │ │ [烘焙全部] [仅烘焙已修改] [验证所有路径连通性] │ └─────────────────────────────────────────────────────────────────┘ ``` --- ### 3.4 SaveData 查看器 **菜单路径**:`BaseGames > World > SaveData Viewer` ``` ┌─ SaveData Viewer ───────────────────────────────────────────────┐ │ Slot 0 | Slot 1 | Slot 2 │ │ ───────────────────────────────────────────────────────────── │ │ Player: HP 5/5 | Geo 340 | Soul 66/99 │ │ Scene: Room_Forest_01 @ SP_Forest_01_Entry │ │ Abilities: Parry✓ DoubleJump✓ WallJump✗ Dash✗ Swim✗ │ │ Discovered: 3 rooms | Cleared: 1 | Bosses Defeated: 0 │ │ ───────────────────────────────────────────────────────────── │ │ [JSON 原始视图] [编辑并保存] [删除此存档] │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 4. Scene 视图 Gizmos 汇总 | 组件 | Gizmo 形状 | 颜色 | 说明 | |------|-----------|------|------| | `HitBox` | BoxWire | 橙色(激活:实心50%透明)| 攻击判定区域 | | `HurtBox` | BoxWire | 绿色(受击中:红色闪烁)| 受击区域 | | `SpawnPoint` | 旗帜Icon + 文字 | 绿色 | 玩家出生点标识 | | `RoomTransition` | 箭头 → 目标场景文字 | 蓝色 | 房间出口方向 | | `RoomCameraBounds` | Polygon + 内层相机视野矩形 | 青色 | 镜头约束范围 | | `EnemyBase` 检测范围 | 圆圈 | 黄色 | 玩家检测半径 | | `EnemyBase` 攻击范围 | 圆圈 | 红色(实线)| 攻击触发范围 | | `EnemyBase` 巡逻路径 | 线段 + 端点 | 蓝色虚线 | 巡逻 A~B 路径 | | `EnemyBase` 寻路目标 | 箭头 | 绿色 | 当前导航目标 | | `EnemyBase` 视线检测 | 射线 | 青色(遮挡:红色)| Raycast 视线 | | `NavLink` | 弧形箭头 | 紫色 | 导航跳跃链接 | | `HazardZone` | BoxWire | 红色(实心30%透明)| 危险区域范围 | | `AbilityUnlock` | 星形Icon | 金色 | 能力解锁物件标识 | | `SavePoint` | 旗帜Icon(已激活/未激活)| 蓝色/灰色 | 存档点状态 | | `ParrySystem`(窗口中)| 圆圈动画 | 黄色 | 弹反窗口激活指示 | --- ## 5. Play Mode 调试叠加层 `DebugOverlayWindow`:按 F1 键(仅 Development Build 和 Editor 中)显示调试叠加层。 ### 叠加层布局 ``` ┌─────────────────────────────────────────────────────────────────┐ │ [F1 关闭] FPS: 144 │ │ │ │ Player State: RunState HP: 8/10 Soul: 66 Geo: 340 │ │ IsGrounded: ✓ Facing: → Invincible: ✗ │ │ │ │ Active Camera: VCam_Explore Blend: Complete │ │ Current Room: Room_Forest_01 │ │ │ │ Enemies in Scene: 2 Alive: 1 Dead: 1 │ │ │ │ ─────────── 快捷键 ─────────────────────────────────────── │ │ F2 切换无敌 F3 加满 Soul F4 下一检查点 F5 重新加载场景 │ │ F6 切换 Gizmos F7 切换碰撞体显示 F8 切换 AI 暂停 │ └─────────────────────────────────────────────────────────────────┘ ``` --- ## 6. ContextMenu 工具 通过 Inspector 右键菜单(`[ContextMenu]`)调用,无需进入 Play Mode: | 组件 | 右键菜单项 | 说明 | |------|----------|------| | `EnemyStatsSO` | `Print Stats Summary` | Console 打印该敌人完整属性表 | | `DamageSourceSO` | `Calculate DPS` | Console 打印理论 DPS(BaseDamage / AttackCooldown)| | `RoomCameraBounds` | `Fit to Room Tilemap` | 自动调整 PolygonCollider2D 以包裹 Tilemap 边界 | | `NavSurface` | `Bake NavMesh` | 立即烘焙此 NavSurface | | `SavePoint` | `Mark As Activated` | 设置 SavePoint 为已激活状态(用于测试继续游戏场景)| | `RoomTransition` | `Validate Target Scene` | 检查目标场景是否存在于 BuildSettings | --- ## 7. 编辑器菜单结构 Unity 菜单栏 `BaseGames/` 下的所有工具入口: ``` BaseGames/ ├── Core/ │ └── Event Channel Monitor → EventChannelMonitorWindow │ ├── World/ │ ├── Room Connection Validator → RoomConnectionValidatorWindow │ ├── SaveData Viewer → SaveDataViewerWindow │ └── Rebuild All Spawn Points → 扫描并重新生成 SpawnPoint ID 索引 │ ├── Navigation/ │ ├── Quick Bake All Rooms → NavSurfaceBakeTool │ └── Validate Path Connectivity → 检查所有房间 NavLink 连通性 │ ├── Combat/ │ └── DPS Calculator → 输入 DamageSourceSO + AttackCooldown,输出 DPS 表格 │ └── Settings/ ├── Open Project Layer Matrix → 快速跳转到 ProjectSettings > Physics2D Layer Matrix └── Validate Assembly Definitions → 检查 .asmdef 依赖关系是否符合零耦合原则 ``` --- ## 8. 自动化检查工具 ### 场景验证检查(保存场景时自动运行) `SceneValidationProcessor`(继承 `AssetModificationProcessor`),在保存场景时自动检查: | 检查项 | 错误级别 | 说明 | |--------|---------|------| | 场景是否有 `RoomCameraBounds` | Warning | 遗漏镜头约束 | | 场景是否有 `NavSurface` | Warning | 有敌人的场景必须有 NavSurface | | 所有 `RoomTransition` 目标场景是否在 BuildSettings | Error | 目标场景不存在 | | 所有 `HitBox` 是否有对应 `DamageSourceSO` | Error | 攻击参数未配置 | | 所有 `EnemyBase` 是否有 `EnemyStatsSO` | Error | 敌人属性未配置 | 检查结果在 Console 窗口输出,并在 `Scene Validation` 浮窗中汇总。 ### Assembly Definition 依赖校验 `BaseGames > Settings > Validate Assembly Definitions` 检查 `.asmdef` 是否遵循零耦合原则(如 `BaseGames.Player` 不应直接依赖 `BaseGames.Enemies`),输出依赖图 Mermaid 格式并在 Console 报警。 --- ## 9. 高级工具集(补充) ### 9.1 Behavior Tree 验证器 `Tools > Zeling > BT Validator`(`BaseGames.Editor.BehaviorTreeValidator`): 扫描 `Assets/` 下所有 Behavior Designer `.asset` 文件,检测: | 检查项 | 级别 | 说明 | |--------|------|------| | 孤立节点(无父节点且非根)| Warning | 表示悬空的设计草稿节点 | | 缺失 TaskName 的 Action/Condition | Error | 会导致 BD 无法编译 | | SharedVariable 引用为空 | Warning | 运行时会 NullRef | | Action 节点最大深度 > 12 | Warning | 过深 BT 建议拆分子树 | | 同一 Agent 上同时存在多个 BehaviorTree 组件 | Error | 会互相覆盖 | 输出到 Console,双击跳转到对应 BD 资产。 ### 9.2 进程流程图(Progression Flow Graph) `Tools > Zeling > Progression Flow Graph`(EditorWindow): ``` ┌─ Progression Flow Graph ─────────────────────────────────────┐ │ [刷新] [导出为 PNG] [高亮未实现节点] │ │ │ │ ┌Forest──────┐ ─击败SpiderGuard→ ┌Cave───────────────┐ │ │ │SP_Forest_01│ │SP_Cave_01 │ │ │ │HP+2 Heart │ │WallJump Unlock │ │ │ └────────────┘ └───────────────────┘ │ │ │ │ │ │ └──────── 需要 Dash ─────────────────┘ │ └──────────────────────────────────────────────────────────────┘ ``` - 自动读取所有 `ProgressLock`/`AbilityGate` SO 及 `BossProgressTracker` 配置 - 用 Bezier 曲线绘制依赖关系(红色=未解锁,绿色=已解锁) - 右键节点 → "模拟解锁" → 在 Editor 中测试后续节点是否变绿 ### 9.3 GameState 转换分析器 `Tools > Zeling > GameState Analyzer`(EditorWindow): - 列出 `GameManager` 中所有 `GameState` 枚举值 - 显示每个状态下:允许的输入 Action Map、哪些 SO 频道被监听 - 矩阵视图:行 = 事件频道,列 = 当前状态;标注"会触发"/"被忽略" - 辅助排查"暂停状态下攻击事件仍被响应"等逻辑漏洞 ### 9.4 伤害模拟器(Damage Simulator) `DamageSourceSO` 右键菜单 → `Simulate Damage`,弹出快速面板: ``` ┌─ Damage Simulator: DamageSource_PlayerAttack1 ──┐ │ 目标防御: 0 [ ] 格 受伤类型: Normal │ │ CharmBonus: × 1.5 + 12(剑尖魅力) │ │ 弱点: × 1.0 [✓] 骑士弱点(十字架) │ │ ───────────────────────────────────────────── │ │ 最终伤害: 14(基础 9 × 1.5 + 1 向上取整) │ │ [运行 1000 次随机伤害分布图] │ └─────────────────────────────────────────────────┘ ``` 不需要进入 Play Mode 即可快速验证伤害数值设计。 ### 9.5 地图贴图验证器(Map Texture Validator) `Tools > Zeling > Map Texture Validator`: - 读取 `MapRoomDataSO.roomOutlineTexture` 与对应场景的实际 Tilemap 边界 - 对比边界框是否对齐(允许 ± 1 tile 误差) - 检测 Texture 是否以 `Read/Write` 导入(SetPixels 需要) - 批量输出不匹配的房间列表 + 截图预览 ### 9.6 音频导入预处理器(Audio Import Preprocessor) `BaseGames.Editor.AudioImportPreprocessor`(继承 `AssetPostprocessor`): 规则表(`AudioImportRulesSO`,可在 Inspector 配置): | 文件名前缀 | 平台 | 采样率 | 压缩格式 | Load Type | |-----------|------|--------|---------|-----------| | `BGM_` | All | 44100 | Vorbis(q=0.4)| Streaming | | `SFX_` | All | 22050 | ADPCM | CompressedInMemory | | `AMB_` | All | 22050 | Vorbis(q=0.3)| Streaming | | `Voice_` | All | 22050 | Vorbis(q=0.6)| CompressedInMemory | 导入音频时自动按文件名前缀应用对应设置,Console 输出 `[AudioPreprocessor] Applied: SFX rule → SFX_Player_Hurt.wav`。 ### 9.7 装备预览工具(Equip Preview) `Tools > Zeling > Equip Preview`(EditorWindow): ``` ┌─ Equip Preview ──────────────────────────────────────────────┐ │ 选择魅力组合(最多 4 个槽位): │ │ 槽1: [剑之力量魅力 ▼] 槽2: [灵魂强化魅力 ▼] │ │ 槽3: [无 ] 槽4: [无 ] │ │ ───────────────────────────────────────────────────────── │ │ 最终属性: │ │ 攻击力: 9 × 1.5 = 13 法术消耗: 33 × 0.67 = 22 │ │ 弹反 Soul: 10 → 10 法术弹数: 3 → 3 │ │ 路径成本: 4 个通知(EquipmentManager.Apply × 4) │ │ [复制配置 JSON] [应用到 Player(Play Mode)] │ └──────────────────────────────────────────────────────────────┘ ``` ### 9.8 构建验证器(Build Validator) `Tools > Zeling > Validate Build`,在正式打包前执行完整检测: | 检测项 | 级别 | |--------|------| | 所有场景已加入 Build Settings | Error | | 所有 `AudioImportRulesSO` 规则已应用 | Warning | | 所有 `AnimationEventConfigSO` 无超出范围的事件时间 | Error | | 所有 `AbilityGate` 引用的能力 ID 存在于 `AbilityType` 枚举 | Error | | 所有 `LocalizationKeys` 常量在 zh-CN StringTable 中有对应条目 | Warning | | Player Prefab 已注册为 Addressable(address = `"Player"`,不使用 `Resources/`)| Error | | 所有 Addressable Group 无缺失引用(Missing Reference)| Error | | `SaveData` JSON Schema 与当前字段一致(版本检查)| Warning | | 构建目标平台 Build Target 与发布目标匹配 | Warning | 输出结果为 Build Validation Report(Text + 每项跳转链接),只有零 Error 才允许继续打包。