refactor(editor): reorganize Editor directory and unify menu hierarchy

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>
This commit is contained in:
2026-05-20 11:52:17 +08:00
parent 442d4c9cfc
commit 82ce9ff09a
38 changed files with 115 additions and 61 deletions

View File

@@ -34,7 +34,7 @@ namespace BaseGames.Editor
private static readonly Color ColMissing = new Color(0.95f, 0.55f, 0.10f, 0.80f); // 无效 Key不在 Addressables private static readonly Color ColMissing = new Color(0.95f, 0.55f, 0.10f, 0.80f); // 无效 Key不在 Addressables
private static readonly Color ColOk = new Color(0.20f, 0.75f, 0.30f, 0.80f); // 正常 private static readonly Color ColOk = new Color(0.20f, 0.75f, 0.30f, 0.80f); // 正常
[MenuItem("BaseGames/Tools/Asset Reference Graph")] [MenuItem("BaseGames/Addressables/Asset Reference Graph")]
public static void OpenWindow() public static void OpenWindow()
{ {
var win = GetWindow<AddressReferenceGraphWindow>("Asset Reference Graph"); var win = GetWindow<AddressReferenceGraphWindow>("Asset Reference Graph");

View File

@@ -25,7 +25,7 @@ namespace BaseGames.Editor
{ {
// ── 常量 ───────────────────────────────────────────────────────────── // ── 常量 ─────────────────────────────────────────────────────────────
private const string Title = "Addressable 批量工具"; private const string Title = "Addressable 批量工具";
private const string MenuPath = "BaseGames/Tools/Addressable Batch Tool"; private const string MenuPath = "BaseGames/Addressables/Addressable Batch Tool";
private const string PrefsKey = "AddressableBatch."; private const string PrefsKey = "AddressableBatch.";
// ── 状态 ───────────────────────────────────────────────────────────── // ── 状态 ─────────────────────────────────────────────────────────────
@@ -77,7 +77,7 @@ namespace BaseGames.Editor
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────
[MenuItem(MenuPath, priority = 200)] [MenuItem(MenuPath, priority = 200)]
[MenuItem("BaseGames/Verification/Open Addressable Batch Tool", priority = 250)] [MenuItem("BaseGames/Addressables/Open Addressable Batch Tool", priority = 250)]
public static void OpenWindow() public static void OpenWindow()
{ {
var win = GetWindow<AddressableBatchTool>(Title); var win = GetWindow<AddressableBatchTool>(Title);

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0547dd5099c322248a3a2652f4b01cc9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 195ffa39c13090d4e94d81ab10b6c721
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -42,7 +42,7 @@ namespace BaseGames.Editor
private readonly Dictionary<int, SerializedObject> _soCache = new Dictionary<int, SerializedObject>(); private readonly Dictionary<int, SerializedObject> _soCache = new Dictionary<int, SerializedObject>();
// ══ 菜单入口 ══════════════════════════════════════════════════════════ // ══ 菜单入口 ══════════════════════════════════════════════════════════
[MenuItem("BaseGames/Camera/Camera Area Setup", priority = 100)] [MenuItem("BaseGames/Scene/Camera Area Setup", priority = 100)]
public static void ShowWindow() public static void ShowWindow()
{ {
var win = GetWindow<CameraAreaSetupTool>("Camera Area Setup"); var win = GetWindow<CameraAreaSetupTool>("Camera Area Setup");

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 07ed02361aa3739468cbd36457aecda6 guid: c58b8b4e1f9da6a42ac3d362d4bf4014
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@@ -38,7 +38,7 @@ namespace BaseGames.Editor
private static StyleSheet Uss => private static StyleSheet Uss =>
_uss != null ? _uss : (_uss = AssetDatabase.LoadAssetAtPath<StyleSheet>(UssPath)); _uss != null ? _uss : (_uss = AssetDatabase.LoadAssetAtPath<StyleSheet>(UssPath));
[MenuItem("BaseGames/Tools/Character Wizard", priority = 1)] [MenuItem("BaseGames/Data/Character Wizard", priority = 1)]
public static void Open() public static void Open()
{ {
var wnd = GetWindow<CharacterWizardWindow>(); var wnd = GetWindow<CharacterWizardWindow>();

View File

@@ -39,7 +39,7 @@ namespace BaseGames.Editor
private static readonly Color ColDelay = new Color(0.25f, 0.25f, 0.30f, 0.50f); private static readonly Color ColDelay = new Color(0.25f, 0.25f, 0.30f, 0.50f);
private static readonly Color ColWarn = new Color(0.95f, 0.10f, 0.10f, 0.85f); private static readonly Color ColWarn = new Color(0.95f, 0.10f, 0.10f, 0.85f);
[MenuItem("BaseGames/Tools/Boss Skill Sequence Viewer")] [MenuItem("BaseGames/Data/Boss Skill Sequence", priority = 110)]
public static void OpenWindow() public static void OpenWindow()
{ {
var win = GetWindow<BossSkillSequenceWindow>("Boss Skill Sequence"); var win = GetWindow<BossSkillSequenceWindow>("Boss Skill Sequence");

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 763f62796f2f4ed43a21dfe3befb70a1 guid: f8e429c47dfa7fe4da6d9687c02398ea
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@@ -18,7 +18,7 @@ namespace BaseGames.Editor
private static readonly PropertyInfo s_bakeJobProp = private static readonly PropertyInfo s_bakeJobProp =
typeof(NavSurface).GetProperty("BakeJob", BindingFlags.NonPublic | BindingFlags.Instance); typeof(NavSurface).GetProperty("BakeJob", BindingFlags.NonPublic | BindingFlags.Instance);
[MenuItem("BaseGames/Tools/Bake All NavSurfaces %#b", priority = 100)] [MenuItem("BaseGames/Scene/Bake All NavSurfaces %#b", priority = 100)]
public static void BakeAll() public static void BakeAll()
{ {
var surfaces = Object.FindObjectsByType<NavSurface>(FindObjectsSortMode.None); var surfaces = Object.FindObjectsByType<NavSurface>(FindObjectsSortMode.None);
@@ -42,7 +42,7 @@ namespace BaseGames.Editor
Debug.Log($"[NavSurfaceBake] 开始烘焙 {count} 个 NavSurface……"); Debug.Log($"[NavSurfaceBake] 开始烘焙 {count} 个 NavSurface……");
} }
[MenuItem("BaseGames/Tools/Bake All NavSurfaces %#b", validate = true)] [MenuItem("BaseGames/Scene/Bake All NavSurfaces %#b", validate = true)]
private static bool BakeAllValidate() private static bool BakeAllValidate()
{ {
// 仅在非 Play Mode 时可用NavSurface.Bake 仅支持编辑器模式) // 仅在非 Play Mode 时可用NavSurface.Bake 仅支持编辑器模式)

View File

@@ -35,7 +35,7 @@ namespace BaseGames.Editor
private static readonly Color ColActive = new Color(0.95f, 0.60f, 0.10f, 0.80f); private static readonly Color ColActive = new Color(0.95f, 0.60f, 0.10f, 0.80f);
private static readonly Color ColPending = new Color(0.70f, 0.70f, 0.75f, 0.80f); private static readonly Color ColPending = new Color(0.70f, 0.70f, 0.75f, 0.80f);
[MenuItem("BaseGames/Tools/Event Chain Viewer")] [MenuItem("BaseGames/Events/Event Chain Viewer")]
public static void OpenWindow() public static void OpenWindow()
{ {
var win = GetWindow<EventChainEditorWindow>("Event Chain Viewer"); var win = GetWindow<EventChainEditorWindow>("Event Chain Viewer");

View File

@@ -18,7 +18,7 @@ namespace BaseGames.Editor
{ {
private const string RootPath = "Assets/_Game/Data/Events"; private const string RootPath = "Assets/_Game/Data/Events";
[MenuItem("BaseGames/Tools/Create Event Channel Assets")] [MenuItem("BaseGames/Events/Create Event Channels")]
public static void CreateAll() public static void CreateAll()
{ {
// ── Core 原始类型频道 ────────────────────────────────────────────── // ── Core 原始类型频道 ──────────────────────────────────────────────
@@ -115,7 +115,7 @@ namespace BaseGames.Editor
Debug.Log("[CreateEventChannelAssets] 所有事件频道资产生成完毕。"); Debug.Log("[CreateEventChannelAssets] 所有事件频道资产生成完毕。");
} }
[MenuItem("BaseGames/Tools/Reimport Event Channel Assets")] [MenuItem("BaseGames/Events/Reimport Event Channels")]
public static void ReimportAllEventAssets() public static void ReimportAllEventAssets()
{ {
if (!AssetDatabase.IsValidFolder(RootPath)) if (!AssetDatabase.IsValidFolder(RootPath))

View File

@@ -13,7 +13,7 @@ namespace BaseGames.Editor
private bool _autoScroll = true; private bool _autoScroll = true;
private Vector2 _scroll; private Vector2 _scroll;
[MenuItem("BaseGames/Tools/Event Bus Monitor %#e")] [MenuItem("BaseGames/Events/Event Bus Monitor %#e")]
public static void OpenWindow() public static void OpenWindow()
{ {
EventBusMonitorWindow window = GetWindow<EventBusMonitorWindow>("Event Bus Monitor"); EventBusMonitorWindow window = GetWindow<EventBusMonitorWindow>("Event Bus Monitor");

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 89f2177f5a1c33044a6c38a2633f0ade
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 172d69bd8cc35c34197a1974bd9cc9c3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -51,7 +51,7 @@ namespace BaseGames.Editor
// ── 菜单入口 ────────────────────────────────────────────────────────── // ── 菜单入口 ──────────────────────────────────────────────────────────
[MenuItem("BaseGames/Tools/Boot Flow Wizard", priority = 10)] [MenuItem("BaseGames/Scene/Setup/Boot Flow Wizard", priority = 10)]
public static void Open() public static void Open()
{ {
var wnd = GetWindow<BootFlowSetupWizard>(); var wnd = GetWindow<BootFlowSetupWizard>();

View File

@@ -15,13 +15,13 @@ namespace BaseGames.Editor
/// 运行时Play Mode / 发行版 Build的保证由 GameBootstrapRuntime 程序集)负责, /// 运行时Play Mode / 发行版 Build的保证由 GameBootstrapRuntime 程序集)负责,
/// 本脚本与 Play Mode 状态无关,不监听 playModeStateChanged。 /// 本脚本与 Play Mode 状态无关,不监听 playModeStateChanged。
/// ///
/// 菜单BaseGames/Tools/Edit Mode: Auto-Open Persistent Scene /// 菜单BaseGames/Scene/Setup/Auto-Open Persistent Scene
/// </summary> /// </summary>
[InitializeOnLoad] [InitializeOnLoad]
public static class PersistentSceneAutoLoader public static class PersistentSceneAutoLoader
{ {
// ── 常量 ───────────────────────────────────────────────────────────── // ── 常量 ─────────────────────────────────────────────────────────────
private const string MenuPath = "BaseGames/Tools/Edit Mode: Auto-Open Persistent Scene"; private const string MenuPath = "BaseGames/Scene/Setup/Auto-Open Persistent Scene";
private const string PrefKey = "BaseGames_EditAutoOpen_Persistent"; private const string PrefKey = "BaseGames_EditAutoOpen_Persistent";
private const string PersistentSceneName = "Scene_Persistent"; private const string PersistentSceneName = "Scene_Persistent";

View File

@@ -26,7 +26,7 @@ namespace BaseGames.Editor
public static class SceneScaffoldTools public static class SceneScaffoldTools
{ {
[MenuItem("BaseGames/Tools/Scaffold Persistent Scene")] [MenuItem("BaseGames/Scene/Setup/Scaffold Persistent Scene")]
public static void ScaffoldPersistentScene() public static void ScaffoldPersistentScene()
{ {
var report = new List<string>(); var report = new List<string>();
@@ -235,7 +235,7 @@ namespace BaseGames.Editor
/// [MainMenu] → [Canvas_MainMenu] → 主按钮组 / SaveSlotPanel / SettingsPanel / CreditsPanel /// [MainMenu] → [Canvas_MainMenu] → 主按钮组 / SaveSlotPanel / SettingsPanel / CreditsPanel
/// 自动绑定所有已存在的相关事件频道 SO 资产。 /// 自动绑定所有已存在的相关事件频道 SO 资产。
/// </summary> /// </summary>
[MenuItem("BaseGames/Tools/Scaffold Main Menu Scene", priority = 202)] [MenuItem("BaseGames/Scene/Setup/Scaffold Main Menu Scene", priority = 202)]
public static void ScaffoldMainMenuScene() public static void ScaffoldMainMenuScene()
{ {
var report = new List<string>(); var report = new List<string>();
@@ -305,7 +305,7 @@ namespace BaseGames.Editor
/// [RoomRoot] → [Camera] / [SpawnPoints] / [Environment] / [Transitions] /// [RoomRoot] → [Camera] / [SpawnPoints] / [Environment] / [Transitions]
/// 可配合 SceneObjectPlacerTool 在层级内快速追加更多对象。 /// 可配合 SceneObjectPlacerTool 在层级内快速追加更多对象。
/// </summary> /// </summary>
[MenuItem("BaseGames/Tools/Scaffold Game Room", priority = 201)] [MenuItem("BaseGames/Scene/Setup/Scaffold Game Room", priority = 201)]
public static void ScaffoldGameRoom() public static void ScaffoldGameRoom()
{ {
var report = new List<string>(); var report = new List<string>();

View File

@@ -15,7 +15,7 @@ namespace BaseGames.Editor
// 场景 // 场景
// ────────────────────────────────────────────── // ──────────────────────────────────────────────
[MenuItem("BaseGames/Tools/Missing Scripts/Clear In Scene")] [MenuItem("BaseGames/Tools/Maintenance/Missing Scripts/Clear In Scene")]
public static void ClearMissingScriptsInScene() public static void ClearMissingScriptsInScene()
{ {
int totalRemoved = 0; int totalRemoved = 0;
@@ -39,7 +39,7 @@ namespace BaseGames.Editor
Debug.Log($"[MissingScriptCleaner] 场景完成。共移除 {totalRemoved} 个丢失脚本,影响 {affected.Count} 个 GameObject。"); Debug.Log($"[MissingScriptCleaner] 场景完成。共移除 {totalRemoved} 个丢失脚本,影响 {affected.Count} 个 GameObject。");
} }
[MenuItem("BaseGames/Tools/Missing Scripts/Find In Scene")] [MenuItem("BaseGames/Tools/Maintenance/Missing Scripts/Find In Scene")]
public static void FindMissingScriptsInScene() public static void FindMissingScriptsInScene()
{ {
int totalFound = 0; int totalFound = 0;
@@ -67,7 +67,7 @@ namespace BaseGames.Editor
// Prefab 资产 // Prefab 资产
// ────────────────────────────────────────────── // ──────────────────────────────────────────────
[MenuItem("BaseGames/Tools/Missing Scripts/Clear In All Prefabs")] [MenuItem("BaseGames/Tools/Maintenance/Missing Scripts/Clear In All Prefabs")]
public static void ClearMissingScriptsInPrefabs() public static void ClearMissingScriptsInPrefabs()
{ {
int totalRemoved = 0; int totalRemoved = 0;
@@ -107,7 +107,7 @@ namespace BaseGames.Editor
Debug.Log($"[MissingScriptCleaner] Prefab 完成。共移除 {totalRemoved} 个丢失脚本,影响 {affectedPrefabs} 个 Prefab。"); Debug.Log($"[MissingScriptCleaner] Prefab 完成。共移除 {totalRemoved} 个丢失脚本,影响 {affectedPrefabs} 个 Prefab。");
} }
[MenuItem("BaseGames/Tools/Missing Scripts/Find In All Prefabs")] [MenuItem("BaseGames/Tools/Maintenance/Missing Scripts/Find In All Prefabs")]
public static void FindMissingScriptsInPrefabs() public static void FindMissingScriptsInPrefabs()
{ {
int totalFound = 0; int totalFound = 0;

View File

@@ -54,14 +54,14 @@ namespace BaseGames.Editor
}; };
// ───────────────────────────────────────────────────────────────────── // ─────────────────────────────────────────────────────────────────────
[MenuItem("BaseGames/Tools/Physics2D Layer Matrix/Check", priority = 210)] [MenuItem("BaseGames/Tools/Maintenance/Physics2D Layer Matrix/Check", priority = 210)]
public static void CheckAndPrintReport() public static void CheckAndPrintReport()
{ {
var results = Check(); var results = Check();
PrintToConsole(results); PrintToConsole(results);
} }
[MenuItem("BaseGames/Tools/Physics2D Layer Matrix/Auto Fix", priority = 211)] [MenuItem("BaseGames/Tools/Maintenance/Physics2D Layer Matrix/Auto Fix", priority = 211)]
public static void FixAndReport() public static void FixAndReport()
{ {
var results = Check(); var results = Check();

View File

@@ -31,7 +31,7 @@ namespace BaseGames.Editor
+ string.Join("\n", errors)); + string.Join("\n", errors));
} }
[MenuItem("BaseGames/Tools/Validate All ScriptableObjects")] [MenuItem("BaseGames/Tools/Validation/Validate All ScriptableObjects")]
public static void ValidateMenu() public static void ValidateMenu()
{ {
var (errors, warnings) = RunAll(); var (errors, warnings) = RunAll();

View File

@@ -32,7 +32,7 @@ namespace BaseGames.Editor
new OrderRule("PlayerController", -100), new OrderRule("PlayerController", -100),
}; };
[MenuItem("BaseGames/Tools/Apply Script Execution Order Preset")] [MenuItem("BaseGames/Tools/Validation/Apply Script Execution Order Preset")]
public static void ApplyPreset() public static void ApplyPreset()
{ {
int updated = 0; int updated = 0;
@@ -69,7 +69,7 @@ namespace BaseGames.Editor
Debug.Log($"[ScriptExecutionOrderTools] 执行顺序预设应用完成。更新数量: {updated}。"); Debug.Log($"[ScriptExecutionOrderTools] 执行顺序预设应用完成。更新数量: {updated}。");
} }
[MenuItem("BaseGames/Tools/Validate Script Execution Order Preset")] [MenuItem("BaseGames/Tools/Validation/Validate Script Execution Order Preset")]
public static void ValidatePreset() public static void ValidatePreset()
{ {
var mismatches = new List<string>(); var mismatches = new List<string>();

View File

@@ -1,5 +1,5 @@
fileFormatVersion: 2 fileFormatVersion: 2
guid: 08a52815a08c8c3428ccb6a530171ddd guid: a1f0dd89654be0841be1adfcea426a67
folderAsset: yes folderAsset: yes
DefaultImporter: DefaultImporter:
externalObjects: {} externalObjects: {}

View File

@@ -652,11 +652,11 @@ var (prefab, _) = await AssetLoader.LoadAsync<GameObject>(AddressKeys.PrefabPlay
4. 在 Animations/ 下创建动画片段(.anim和 Animator Controller 4. 在 Animations/ 下创建动画片段(.anim和 Animator Controller
5. 在 Materials/ 下创建材质(引用 _Game/Shaders/ 中的角色 Shader关联主纹理和 Emission 贴图) 5. 在 Materials/ 下创建材质(引用 _Game/Shaders/ 中的角色 Shader关联主纹理和 Emission 贴图)
6. 在 Atlases/ 下创建 Atlas_Enemy_{ID}.spriteatlas包含该敌人所有 Sprite 6. 在 Atlases/ 下创建 Atlas_Enemy_{ID}.spriteatlas包含该敌人所有 Sprite
7. 在 Enemy Data Manager菜单 BaseGamesDataEnemy Data Manager创建 ENM_{ID}_Stats.asset 7. 在 Enemy Data Manager菜单 BaseGames/Data/Enemy Data Manager创建 ENM_{ID}_Stats.asset
8. 在 _Game/Prefabs/Enemies/{EnemyID}/ 下创建 ENM_{Name}.prefab 8. 在 _Game/Prefabs/Enemies/{EnemyID}/ 下创建 ENM_{Name}.prefab
9. 在 AddressKeys.cs 中添加 PrefabEnemy{Name} 常量 9. 在 AddressKeys.cs 中添加 PrefabEnemy{Name} 常量
10. 使用 Rule Sync菜单 BaseGamesAddressablesRule SyncScan → Fix All自动分组并打 Enemy 标签 10. 使用 Rule Sync菜单 BaseGames/Addressables/Rule SyncScan → Fix All自动分组并打 Enemy 标签
11. 运行 AddressKeyValidator菜单 BaseGames → Verification → Validate Address Keys验证 11. 运行 AddressKeyValidator菜单 BaseGames/Addressables/Validate Address Keys验证
``` ```
### 10.2 新增武器Weapon ### 10.2 新增武器Weapon
@@ -665,10 +665,10 @@ var (prefab, _) = await AssetLoader.LoadAsync<GameObject>(AddressKeys.PrefabPlay
``` ```
1. 在 _Game/Art/Characters/Player/{FormID}/Sprites/ 下放置武器帧动画 Sprite Sheet配置 Import Settings 1. 在 _Game/Art/Characters/Player/{FormID}/Sprites/ 下放置武器帧动画 Sprite Sheet配置 Import Settings
2. 在 Weapon Editor菜单 BaseGamesDataWeapon Editor左栏 [New] 创建 WPN_{Name}_Data.asset 2. 在 Weapon Editor菜单 BaseGames/Data/Weapon Editor左栏 [New] 创建 WPN_{Name}_Data.asset
- 路径_Game/Data/Combat/Weapons/WPN_{Name}_Data.asset - 路径_Game/Data/Combat/Weapons/WPN_{Name}_Data.asset
- 命名WPN_{Name}示例WPN_SkyBlade、WPN_EarthClaw - 命名WPN_{Name}示例WPN_SkyBlade、WPN_EarthClaw
3. 使用 Weapon HitBox Wizard菜单 BaseGamesCreateWeapon HitBox Prefab生成 3. 使用 Weapon HitBox Wizard菜单 BaseGames/Create/Weapon HitBox Prefab生成
_Game/Prefabs/Weapons/WPN_{Name}_HitBox.prefab自动创建 4 方向 Ground/Up/Down/Air _Game/Prefabs/Weapons/WPN_{Name}_HitBox.prefab自动创建 4 方向 Ground/Up/Down/Air
4. 在 _Game/Prefabs/Player/ 下创建或更新武器顶级 Prefab WPN_{Name}.prefab 4. 在 _Game/Prefabs/Player/ 下创建或更新武器顶级 Prefab WPN_{Name}.prefab
5. 在 AddressKeys.cs 中添加 PrefabWeapon{Name} 常量 5. 在 AddressKeys.cs 中添加 PrefabWeapon{Name} 常量
@@ -682,10 +682,10 @@ var (prefab, _) = await AssetLoader.LoadAsync<GameObject>(AddressKeys.PrefabPlay
``` ```
1. 在 _Game/Art/Characters/Player/{FormID}/Animations/ 下创建技能动画片段(.anim 1. 在 _Game/Art/Characters/Player/{FormID}/Animations/ 下创建技能动画片段(.anim
2. 在 Skill Editor菜单 BaseGamesDataSkill Editor左栏 [New] 创建 SKL_{SkillID}_Data.asset 2. 在 Skill Editor菜单 BaseGames/Data/Skill Editor左栏 [New] 创建 SKL_{SkillID}_Data.asset
- 路径_Game/Data/Player/Skills/SKL_{SkillID}_Data.asset - 路径_Game/Data/Player/Skills/SKL_{SkillID}_Data.asset
- 命名SKL_{SkillID}示例SKL_DashSlash、SKL_SpiritWave - 命名SKL_{SkillID}示例SKL_DashSlash、SKL_SpiritWave
3. 使用 Skill HitBox Wizard菜单 BaseGamesCreateSkill HitBox Prefab生成 3. 使用 Skill HitBox Wizard菜单 BaseGames/Create/Skill HitBox Prefab生成
_Game/Prefabs/Skills/SKL_{SkillID}_HitBox.prefab支持多段伤害配置 _Game/Prefabs/Skills/SKL_{SkillID}_HitBox.prefab支持多段伤害配置
4. 在 AddressKeys.cs 中添加对应常量(如需独立 Addressable 加载) 4. 在 AddressKeys.cs 中添加对应常量(如需独立 Addressable 加载)
5. 运行 AddressKeyValidator 验证(如已注册 Addressable 5. 运行 AddressKeyValidator 验证(如已注册 Addressable
@@ -709,11 +709,11 @@ var (prefab, _) = await AssetLoader.LoadAsync<GameObject>(AddressKeys.PrefabPlay
> **推荐工具**`BaseGames → Tools → Character Wizard``CharacterWizardWindow`)统一入口——创建 FormSO、绑定武器引用、跳转到 Form Editor`BaseGames → Data → Form Editor``FormEditorWindow`)进行三魂列阵可视化编辑。 > **推荐工具**`BaseGames → Tools → Character Wizard``CharacterWizardWindow`)统一入口——创建 FormSO、绑定武器引用、跳转到 Form Editor`BaseGames → Data → Form Editor``FormEditorWindow`)进行三魂列阵可视化编辑。
``` ```
1. 在 Character Wizard菜单 BaseGames → Tools → Character Wizard切换到 Player 标签 1. 在 Character Wizard菜单 BaseGames/Data/Character Wizard切换到 Player 标签
- 填写 FormID点击 [Create Form Assets],自动在正确路径创建 FormSO 和相关 SO - 填写 FormID点击 [Create Form Assets],自动在正确路径创建 FormSO 和相关 SO
2. 在 _Game/Art/Characters/Player/{FormID}/ 下创建 Sprites/ Animations/ Materials/ Atlases/ 目录 2. 在 _Game/Art/Characters/Player/{FormID}/ 下创建 Sprites/ Animations/ Materials/ Atlases/ 目录
3. 导入 Sprite Sheet配置 Import SettingsPPU=32, Filter=Point, Multiple 3. 导入 Sprite Sheet配置 Import SettingsPPU=32, Filter=Point, Multiple
4. 在 Form Editor菜单 BaseGamesDataForm Editor三栏网格中选择形态格位绑定武器和技能列表 4. 在 Form Editor菜单 BaseGames/Data/Form Editor三栏网格中选择形态格位绑定武器和技能列表
5. 在 _Game/Prefabs/Player/ 下创建 PLY_{FormID}.prefab 5. 在 _Game/Prefabs/Player/ 下创建 PLY_{FormID}.prefab
6. 在 AddressKeys.cs 中添加 PrefabPlayer{FormID} 常量(如为独立 Addressable 6. 在 AddressKeys.cs 中添加 PrefabPlayer{FormID} 常量(如为独立 Addressable
7. 使用 Rule Sync 自动分组Player 组)并打 Preload 标签 7. 使用 Rule Sync 自动分组Player 组)并打 Preload 标签
@@ -783,40 +783,56 @@ var (prefab, _) = await AssetLoader.LoadAsync<GameObject>(AddressKeys.PrefabPlay
| 工具名称 | 菜单路径 | 负责资产类型 | 说明 | | 工具名称 | 菜单路径 | 负责资产类型 | 说明 |
|---------|---------|------------|------| |---------|---------|------------|------|
| **Character Wizard** | `BaseGames → Tools → Character Wizard` | 角色 SO玩家形态 / Minion / Boss 通用入口) | 统一入口,自动在正确路径创建所有配套 SO内含快捷跳转按钮 | | **Character Wizard** | `BaseGames/Data/Character Wizard` | 角色 SO玩家形态 / Minion / Boss 通用入口) | 统一入口,自动在正确路径创建所有配套 SO内含快捷跳转按钮 |
| **Form Editor** | `BaseGamesDataForm Editor` | 玩家三魂形态FormSO | 三栏可视化网格,自动绑定武器/技能引用,支持 TianHun / DiHun / MingHun | | **Form Editor** | `BaseGames/Data/Form Editor` | 玩家三魂形态FormSO | 三栏可视化网格,自动绑定武器/技能引用,支持 TianHun / DiHun / MingHun |
| **Enemy Data Manager** | `BaseGamesDataEnemy Data Manager` | 敌人配置 SO`ENM_*_Stats.asset`+ 掉落表 | 双面板列表编辑,左栏搜索 + [New],右栏 Stats/Loot 标签 | | **Enemy Data Manager** | `BaseGames/Data/Enemy Data Manager` | 敌人配置 SO`ENM_*_Stats.asset`+ 掉落表 | 双面板列表编辑,左栏搜索 + [New],右栏 Stats/Loot 标签 |
| **Weapon Editor** | `BaseGamesData → Weapon Editor` | 武器配置 SO`WPN_*_Data.asset` | 双面板列表,右栏全属性 + HitBox Prefab 验证 + 快捷操作 | | **Boss Skill Sequence** | `BaseGames/Data/Boss Skill Sequence` | Boss 技能阶段BossSkillSO / SkillSequenceSO | Gantt 时间轴可视化Windup / Active / Recovery 三段颜色标记 |
| **Weapon HitBox Wizard** | `BaseGames → Create → Weapon HitBox Prefab` | 武器 HitBox Prefab4 方向 Ground/Up/Down/Air | 自动生成 `WPN_{ID}_HitBox.prefab`,支持各方向碰撞体形状配置 | | **Skill Editor** | `BaseGames/Data/Skill Editor` | 技能配置 SO`SKL_*_Data.asset` | 按 SkillEffectType 分组筛选,右栏含 HitBox 验证 + 资源费预览 |
| **Skill Editor** | `BaseGamesData → Skill Editor` | 技能配置 SO`SKL_*_Data.asset` | 按 SkillEffectType 分组筛选,右栏含 HitBox 验证 + 资源费预览 | | **Weapon Editor** | `BaseGames/Data/Weapon Editor` | 武器配置 SO`WPN_*_Data.asset` | 双面板列表,右栏全属性 + HitBox Prefab 验证 + 快捷操作 |
| **Skill HitBox Wizard** | `BaseGamesCreate → Skill HitBox Prefab` | 技能 HitBox Prefab多段伤害支持 | 自动生成 `SKL_{ID}_HitBox.prefab`可配置 14 段 hitBoxCount | | **Weapon HitBox Wizard** | `BaseGames/Create/Weapon HitBox Prefab` | 武器 HitBox Prefab4 方向 Ground/Up/Down/Air | 自动生成 `WPN_{ID}_HitBox.prefab`支持各方向碰撞体形状配置 |
| **Boss Skill Sequence** | `BaseGames → Tools → Boss Skill Sequence Viewer` | Boss 技能阶段BossSkillSO / SkillSequenceSO | Gantt 时间轴可视化Windup / Active / Recovery 三段颜色标记 | | **Skill HitBox Wizard** | `BaseGames/Create/Skill HitBox Prefab` | 技能 HitBox Prefab多段伤害支持 | 自动生成 `SKL_{ID}_HitBox.prefab`,可配置 14 段 hitBoxCount |
### 12.2 场景搭建工具 ### 12.2 场景搭建工具
| 工具名称 | 菜单路径 | 说明 | | 工具名称 | 菜单路径 | 说明 |
|---------|---------|------| |---------|---------|------|
| **Boot Flow Wizard** | `BaseGames → Tools → Boot Flow Wizard` | 4 步启动流程一键配置(事件频道 → Persistent 场景 → MainMenu → 验证) | | **Boot Flow Wizard** | `BaseGames/Scene/Setup/Boot Flow Wizard` | 4 步启动流程一键配置(事件频道 → Persistent 场景 → MainMenu → 验证) |
| **Scene Scaffold** | `BaseGames → Tools → Scaffold Persistent Scene` | 一键创建 Persistent 场景的 Services/Input/Camera/UI 层次结构 | | **Scaffold Persistent Scene** | `BaseGames/Scene/Setup/Scaffold Persistent Scene` | 一键创建 Persistent 场景的 Services/Input/Camera/UI 层次结构 |
| **Scene Object Placer** | `BaseGamesScene → Place → {类型}` | 场景中快速放置角色/陷阱/检查点/摄像机等,自动绑定组件和事件频道 | | **Scaffold Main Menu Scene** | `BaseGames/Scene/Setup/Scaffold Main Menu Scene` | 一键创建 MainMenu 场景基础层次结构 |
| **Persistent Auto-Loader** | `BaseGames → Tools → Edit Mode: Auto-Open Persistent Scene` | 编辑模式下打开任意场景时自动附加 Persistent仅编辑模式 | | **Scaffold Game Room** | `BaseGames/Scene/Setup/Scaffold Game Room` | 一键创建关卡房间场景基础层次结构 |
| **Persistent Auto-Loader** | `BaseGames/Scene/Setup/Auto-Open Persistent Scene` | 编辑模式下打开任意场景时自动附加 PersistentToggle仅编辑模式 |
| **Scene Object Placer** | `BaseGames/Scene/Place/{类型}` | 场景中快速放置角色/陷阱/检查点/摄像机等,自动绑定组件和事件频道 |
| **Camera Area Setup** | `BaseGames/Scene/Camera Area Setup` | 在当前场景中快速创建并配置摄像机区域 |
| **Bake All NavSurfaces** | `BaseGames/Scene/Bake All NavSurfaces` (Ctrl+Shift+B) | 一键烘焙场景中所有 NavSurface仅编辑模式可用 |
### 12.3 Addressables 管理工具 ### 12.3 Addressables 管理工具
| 工具名称 | 菜单路径 | 说明 | | 工具名称 | 菜单路径 | 说明 |
|---------|---------|------| |---------|---------|------|
| **Rule Sync** | `BaseGamesAddressablesRule Sync` | 批量扫描/修复分组和标签(基于 `AddressableRules.cs` 规则,支持导出 CSV | | **Rule Sync** | `BaseGames/Addressables/Rule Sync` | 批量扫描/修复分组和标签(基于 `AddressableRules.cs` 规则,支持导出 CSV |
| **Addressable Batch Tool** | `BaseGames → Tools → Addressable Batch Tool` | 三标签操作:① 同步 AddressKeys → ② 文件夹批量注册 → ③ Selection 注册 | | **Addressable Batch Tool** | `BaseGames/Addressables/Addressable Batch Tool` (Alt+Shift+A) | 三标签操作:① 同步 AddressKeys → ② 文件夹批量注册 → ③ Selection 注册 |
| **Validate Address Keys** | `BaseGames → Verification → Validate Address Keys` | 验证 `AddressKeys.cs` 所有常量在 Addressables 中均已注册,构建前自动触发 | | **Asset Reference Graph** | `BaseGames/Addressables/Asset Reference Graph` | 可视化 Addressable 地址间的引用依赖关系 |
| **Validate Address Keys** | `BaseGames/Addressables/Validate Address Keys` | 验证 `AddressKeys.cs` 所有常量在 Addressables 中均已注册,构建前自动触发 |
### 12.4 数据/调试工具 ### 12.4 事件系统工具
| 工具名称 | 菜单路径 | 说明 | | 工具名称 | 菜单路径 | 说明 |
|---------|---------|------| |---------|---------|------|
| **SO Manager** | `BaseGames → Tools → SO Manager` | 全项目 ScriptableObject 浏览器,支持类型/路径搜索 + Ping | | **Event Bus Monitor** | `BaseGames/Events/Event Bus Monitor` (Ctrl+Shift+E) | 运行时事件派发监控(类型/侦听器数/触发次数实时显示) |
| **Event Bus Monitor** | `BaseGames → Tools → Event Bus Monitor` | 运行时事件派发监控(类型/侦听器数/触发次数实时显示) | | **Event Chain Viewer** | `BaseGames/Events/Event Chain Viewer` | 叙事事件链可视化,运行时显示完成/满足/等待状态 |
| **Create Event Channel Assets** | `BaseGames → Tools → Create Event Channel Assets` | 一键生成全局事件频道 SO幂等跳过已存在资产 | | **Create Event Channels** | `BaseGames/Events/Create Event Channels` | 一键生成全局事件频道 SO幂等跳过已存在资产 |
| **GM Debug Tool** | `BaseGames → Tools → GM Debug Tool` | 运行时快速注入资源/切换形态/解锁技能(仅 PlayMode | | **Reimport Event Channels** | `BaseGames/Events/Reimport Event Channels` | 重新导入/刷新全局事件频道 SO |
| **Validate All ScriptableObjects** | `BaseGames → Tools → Validate All ScriptableObjects` | 扫描所有 `IValidatable` SO 并报告错误(构建前自动触发) |
> **原则**:新增资产类型时,必须同步在对应编辑器工具中增加创建入口;严禁绕过工具手动在 Project 窗口 "Create" 并手动填写路径/命名,否则将导致 Addressables Rule Sync 工具误报分组或标签不一致。 ### 12.5 工具与维护
| 工具名称 | 菜单路径 | 说明 |
|---------|---------|------|
| **SO Manager** | `BaseGames/Tools/SO Manager` | 全项目 ScriptableObject 浏览器,支持类型/路径搜索 + Ping |
| **GM Debug Tool** | `BaseGames/Tools/GM Debug Tool` | 运行时快速注入资源/切换形态/解锁技能(仅 PlayMode |
| **Validate All SOs** | `BaseGames/Tools/Validation/Validate All ScriptableObjects` | 扫描所有 `IValidatable` SO 并报告错误(构建前自动触发) |
| **Apply Script Order** | `BaseGames/Tools/Validation/Apply Script Execution Order Preset` | 将脚本执行顺序预设应用到项目 |
| **Validate Script Order** | `BaseGames/Tools/Validation/Validate Script Execution Order Preset` | 验证当前脚本执行顺序是否符合预设 |
| **Missing Scripts (Scene)** | `BaseGames/Tools/Maintenance/Missing Scripts/...` | 在场景/Prefab 中查找或清除 Missing Script 引用 |
| **Physics2D Layer Matrix** | `BaseGames/Tools/Maintenance/Physics2D Layer Matrix/...` | 检查或自动修复 Physics2D 层碰撞矩阵配置 |
> **原则**:新增资产类型时,必须同步在对应编辑器工具中增加创建入口;严禁绕过工具手动在 Project 窗口 "Create" 并手动填写路径/命名,否则将导致 Addressables Rule Sync 工具误报分组或标签不一致。