feat: Addressables rules/sync tools, UI fixes, AddressKeys update

- Add AddressableRules.cs: single source of truth for prefix->group and prefix->label rules
- Add AddressableRuleSyncWindow.cs: scan/fix/export-CSV tool (BaseGames > Addressables > Rule Sync)
- AddressableBatchTool.cs: delegate DeriveGroupName to AddressableRules, remove duplicate PrefixGroupMap
- AddressKeys.cs: add Labels constants (Preload, Poolable, Enemy, BGM, SFX, Charms, Config, Weapon)
- Docs/Standards/AddressablesLabelSpec.md: new label naming & assignment spec
- Docs/Standards/AssetFolderSpec.md: update Addressables group strategy section
- SplashScreenController.cs: fix MainMenu loading flow
- BootFlowSetupWizard.cs / SceneScaffoldTools.cs: scene scaffold fixes
- PlayerInputActions: set UI/Point to Pass-Through type
- Persistent.unity: add BootSequencer to auto-load MainMenu on play
- EditorBuildSettings.asset: register scenes for build

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
2026-05-20 11:10:31 +08:00
parent 5fd981f5b9
commit c88d2d0549
46 changed files with 6099 additions and 2588 deletions

View File

@@ -0,0 +1,262 @@
# Addressables Label标签命名与使用规范
> **版本**1.0
> **创建日期**2026-05
> **适用范围**`Assets/_Game/` 目录下所有注册到 Addressables 的资产
> **关联文档**`Standards/AssetFolderSpec.md §8`、`Scripts/Core/Assets/AddressKeys.cs`
---
## 目录
1. [设计原则](#1-设计原则)
2. [Label 清单](#2-label-清单)
3. [每类资产的 Label 分配](#3-每类资产的-label-分配)
4. [AddressKeys.cs 常量对照](#4-addresskeyscs-常量对照)
5. [使用规范与禁止行为](#5-使用规范与禁止行为)
6. [新增 Label 决策流程](#6-新增-label-决策流程)
---
## 1. 设计原则
### 1.1 Label 的作用
Addressable **Label** 是为"需要按类别批量操作"而设计的:
- **批量下载依赖**BootSequencer 预热)
- **批量加载资产列表**`Addressables.LoadAssetsAsync<T>(label, ...)`
- **构建分析/验证工具**筛选特定类别的资产
> **Label ≠ Group。** Group 决定打包策略(打入哪个 bundle、何时加载卸载Label 决定运行时如何批量引用。一个资产可同时属于某 Group 且带有多个 Label。
### 1.2 Label 命名格式
```
PascalCase不加前缀英文单词或词组
```
-`Poolable``Preload``Enemy`
-`lbl_poolable``POOLABLE``可对象池`
### 1.3 Label 膨胀控制
新增 Label 前必须满足**至少一条**
1. 有代码通过该 Label 进行 **批量异步加载**`LoadAssetsAsync`
2.**BootSequencer 预热需求**`DownloadDependenciesAsync`
3. 有 **编辑器工具**需要按 Label 筛选/校验资产
纯用于分类记录但代码不引用的标签,**不得创建**——用文件夹路径或 Group 命名代替。
---
## 2. Label 清单
| Label | 代码常量 | 用途 | 使用者 |
|-------|---------|------|--------|
| `Preload` | `AddressKeys.Labels.Preload` | 游戏启动时通过 `DownloadDependenciesAsync` 预热下载依赖。涵盖所有首帧可能用到的资产。 | `BootSequencer` |
| `Poolable` | `AddressKeys.Labels.Poolable` | 纳入 `GlobalObjectPool` 管理的 Prefab。标记此标签意味着该资产**必须**在 `GlobalObjectPool._warmupConfigs` 中配置初始池数量。 | `GlobalObjectPool``AddressKeyValidator` |
| `Enemy` | `AddressKeys.Labels.Enemy` | 所有敌人顶级 Prefab。用于区域 Spawner 通过 `LoadAssetsAsync<GameObject>(Labels.Enemy, ...)` 批量加载该区域敌人,或工具统计敌人总数。 | 区域 EnemySpawner待实现 |
| `BGM` | `AddressKeys.Labels.BGM` | 背景音乐 AudioClip 或 FMOD bank 引用 SO。`AudioManager` 通过此标签批量加载 BGM 目录,按 ID 播放。 | `AudioManager` |
| `SFX` | `AddressKeys.Labels.SFX` | 音效 AudioClip 或 SFX 配置 SO。与 `BGM` 平行,供 `AudioManager` 批量建立 SFX 索引。 | `AudioManager` |
| `Charms` | `AddressKeys.Labels.Charms` | 所有护身符配置 SO`CHM_*.asset`)。`EquipmentManager` / 护身符选择 UI 通过此标签加载完整护身符列表,无需逐一引用。 | `EquipmentManager`、护身符选择界面 |
| `Config` | `AddressKeys.Labels.Config` | 运行时**动态加载**的配置类 SO`Config/FootstepCatalog`)。**静态引用**Inspector 直接拖拽)的 SO 不加此标签。 | `AssetLoader`、各需要延迟加载配置的系统 |
| `Weapon` | `AddressKeys.Labels.Weapon` | 所有武器 Prefab`WPN_*.prefab`)。玩家换形态时通过此标签加载对应武器列表,避免硬编码每把武器地址。 | `PlayerFormController`(待实现) |
---
## 3. 每类资产的 Label 分配
### 3.1 场景Scenes
| Address | 所在 Group | Labels |
|---------|-----------|--------|
| `Scene_Persistent` | `Scenes` | ——(常驻,无需 Label |
| `Scene_MainMenu` | `Scenes` | `Preload` |
| `Room_{Region}_{nn}` | `Room_{Region}` | ——(区域加载时整组载入) |
| `Boss_{Name}` | `Boss_{Name}` | ——Boss 战前整组载入) |
> 测试专用场景(`Scenes/Testings/`**不注册 Addressable**,不分配任何 Label。
---
### 3.2 玩家Player
| Address | Labels | 说明 |
|---------|--------|------|
| `PLY_Player` | `Preload` | 玩家 Prefab 在进入 Gameplay 前必须就绪 |
---
### 3.3 敌人Enemies
| Address | Labels | 说明 |
|---------|--------|------|
| `ENM_GruntWarrior` | `Enemy` | 无 `Preload`:区域加载时按需拉取 |
| `ENM_SkullArcher` | `Enemy` | 同上 |
| 新增敌人 `ENM_{Name}` | `Enemy` | 所有敌人必须加此 Label |
> 高频召唤的敌人(每关必出现)可**额外加 `Preload`** 参与启动预热。
---
### 3.4 投射物Projectiles
| Address | Labels | 说明 |
|---------|--------|------|
| `PROJ_Arrow` | `Poolable`, `Preload` | 对象池 + 启动预热 |
| `PROJ_Fireball` | `Poolable`, `Preload` | 同上 |
| `PROJ_SoulBall` | `Poolable`, `Preload` | 同上 |
| 新增 `PROJ_{Name}` | `Poolable`, `Preload` | 默认双标签 |
---
### 3.5 特效VFX
| Address | Labels | 说明 |
|---------|--------|------|
| `VFX_HitSpark` | `Poolable`, `Preload` | 命中特效,高频使用 |
| `VFX_BloodSplat` | `Poolable`, `Preload` | 同上 |
| `VFX_Explosion` | `Poolable`, `Preload` | 同上 |
| 新增通用 VFX | `Poolable`, `Preload` | 高频共用特效默认双标签 |
| 区域专属 VFX | `Poolable` | 仅 `Poolable`,不加 `Preload`(区域加载时预热) |
---
### 3.6 UI Prefab
| Address | Labels | 说明 |
|---------|--------|------|
| `UI_FloatingDamageText` | `Poolable`, `Preload` | 对象池 Prefab战斗中高频出现 |
| 其余 UI 面板 `UI_{Name}` | ——(或 `Preload` | 按需加载;全局常驻面板加 `Preload` |
---
### 3.7 收集物Collectibles
| Address | Labels | 说明 |
|---------|--------|------|
| `COL_LingZhu` | `Poolable`, `Preload` | 灵珠,战斗中高频掉落 |
| `COL_Item` | `Poolable`, `Preload` | 道具掉落 |
| `COL_HPOrb` | `Poolable`, `Preload` | 血球,战斗中高频掉落 |
| 新增 `COL_{Name}` | `Poolable`, `Preload` | 默认双标签 |
---
### 3.8 武器Weapons
| Address | Labels | 说明 |
|---------|--------|------|
| `WPN_SkyBlade` | `Weapon`, `Preload` | 默认形态武器,启动时预热 |
| `WPN_EarthClaw` | `Weapon`, `Preload` | 同上 |
| `WPN_SoulStaff` | `Weapon`, `Preload` | 同上 |
| 新增 `WPN_{Name}` | `Weapon` | 是否加 `Preload` 视形态是否为默认形态 |
---
### 3.9 护身符Charms
| Address | Labels | 说明 |
|---------|--------|------|
| `CHM_{Name}` | `Charms` | 所有护身符 SO 统一加此标签,供 EquipmentManager 批量加载 |
> 护身符 SO 不加 `Preload`——玩家进入装备界面时再批量拉取,不影响启动速度。
---
### 3.10 配置数据Config
| Address | Labels | 说明 |
|---------|--------|------|
| `Config/FootstepCatalog` | `Config`, `Preload` | 脚步音频目录Gameplay 开始前必须就绪 |
| 新增 `Config/{Name}` | `Config` | 是否加 `Preload` 视是否在 Gameplay 首帧使用 |
---
### 3.11 音频Audio
| Address | Labels | 说明 |
|---------|--------|------|
| BGM 资源 `AUD_BGM_{Name}` | `BGM` | AudioManager 批量建立 BGM 索引 |
| SFX 资源 `AUD_SFX_{Name}` | `SFX` | AudioManager 批量建立 SFX 索引 |
> 音频资源不加 `Preload`——由 AudioManager 在 BGM 播放前异步流式加载。
---
## 4. AddressKeys.cs 常量对照
代码中使用 Label 时,**禁止硬编码字符串**,统一引用 `AddressKeys.Labels` 内的常量:
```csharp
// ✅ 正确
await Addressables.DownloadDependenciesAsync(AddressKeys.Labels.Preload, false);
var enemies = await Addressables.LoadAssetsAsync<GameObject>(AddressKeys.Labels.Enemy, null);
// ❌ 禁止
await Addressables.DownloadDependenciesAsync("Preload", false);
```
当前 `AddressKeys.Labels` 完整清单:
| 常量 | 字符串值 |
|------|---------|
| `AddressKeys.Labels.Preload` | `"Preload"` |
| `AddressKeys.Labels.Poolable` | `"Poolable"` |
| `AddressKeys.Labels.Enemy` | `"Enemy"` |
| `AddressKeys.Labels.BGM` | `"BGM"` |
| `AddressKeys.Labels.SFX` | `"SFX"` |
| `AddressKeys.Labels.Charms` | `"Charms"` |
| `AddressKeys.Labels.Config` | `"Config"` |
| `AddressKeys.Labels.Weapon` | `"Weapon"` |
> 每次新增 Label 常量,同步在 Addressables Groups 窗口中创建同名标签,并在此文档 §2 增加说明行。
---
## 5. 使用规范与禁止行为
### 5.1 多标签组合规则
一个资产可同时附加多个 Label组合语义如下
| 组合 | 含义 |
|------|------|
| `Poolable` + `Preload` | 启动预热依赖 + 纳入对象池,适用于高频 VFX、投射物、收集物 |
| `Enemy` + `Preload` | 高频召唤敌人,启动时下载依赖(实例化仍由 Spawner 按需触发) |
| `Config` + `Preload` | 首帧必须可用的配置 SO |
| `Charms` 单独 | 进入装备界面时才批量加载,不参与启动预热 |
### 5.2 禁止行为
| 禁止 | 原因 |
|------|------|
| 给 **ScriptableObject 事件频道**`EVT_*.asset`)加任何 Label | 事件频道通过 Inspector 直接引用,不走 Addressables |
| 给 **子 Prefab**HitBox、HurtBox、骨骼节点加任何 Label | 子对象不单独注册 Addressable |
| 给 **Atlas**`.spriteatlas`)加任何 Label | Atlas 由 Prefab/Material 间接引用,无需 Label |
| 给 **Shader / Material** 加任何 Label | 随 Prefab 打包,无独立 Label 需求 |
| 给 **测试场景**`Scenes/Testings/`)加任何 Label | 不进入 Addressables不可加 Label |
| 代码中直接写字符串 Label`"Poolable"` | 必须用 `AddressKeys.Labels.Poolable` 常量 |
---
## 6. 新增 Label 决策流程
```
需要新增 Label
├── 是否有代码通过该 Label 执行 LoadAssetsAsync
│ ├── 是 → 可新增
│ └── 否 → 是否为 BootSequencer 预热需求?
│ ├── 是 → 可新增(并入 Preload不新建
│ └── 否 → 是否为编辑器验证工具需求?
│ ├── 是 → 可新增(文档注明仅供工具使用)
│ └── 否 → ❌ 不允许新增(用 Group 或文件夹替代)
新增 Label 的执行步骤:
1. 在 AddressKeys.Labels 类中添加 public const string {Name} = "{Name}";
2. 在 Addressables Groups 窗口 → Label 列表中创建同名标签
3. 在本文档 §2 Label 清单中追加说明行
4. 在本文档 §3 对应资产类型的表格中标注
5. 运行 AddressKeyValidator 验证无遗漏
```

View File

@@ -512,16 +512,21 @@ Config/DifficultyEasy
### 8.3 Label标签使用规范
> 完整定义见 `Standards/AddressablesLabelSpec.md`。
| 标签 | 用途 | 相关常量 |
|------|------|---------|
| `Enemy` | 所有敌人 Prefab用于 `LoadAssetsAsync` 批量实例化 | `AddressKeys.Labels.Enemy` |
| `Poolable` | 纳入对象池管理的 PrefabVFX、射物、收集物等)| `AddressKeys.Labels.Poolable` |
| `BGM` | BGM 音频资源FMOD bank 或 AudioClip | `AddressKeys.Labels.BGM` |
| `Charms` | 所有护身符 Prefab/SO用于护身符列表加载 | `AddressKeys.Labels.Charms` |
| `Preload` | 游戏启动时必须预加载的资产 | (待添加常量) |
| `Preload` | 游戏启动时通过 `DownloadDependenciesAsync` 预热下载依赖 | `AddressKeys.Labels.Preload` |
| `Poolable` | 纳入 `GlobalObjectPool` 对象池管理的 PrefabVFX、射物、收集物等)| `AddressKeys.Labels.Poolable` |
| `Enemy` | 所有敌人 Prefab用于区域 Spawner `LoadAssetsAsync` 批量加载 | `AddressKeys.Labels.Enemy` |
| `BGM` | BGM 音频 AudioClip / FMOD bank 引用 SO | `AddressKeys.Labels.BGM` |
| `SFX` | 音效 AudioClip / SFX 配置 SO | `AddressKeys.Labels.SFX` |
| `Charms` | 所有护身符配置 SO供 EquipmentManager 批量加载列表 | `AddressKeys.Labels.Charms` |
| `Config` | 运行时动态加载的配置类 SO | `AddressKeys.Labels.Config` |
| `Weapon` | 所有武器 Prefab玩家换形态时批量加载 | `AddressKeys.Labels.Weapon` |
- 一个资产可附加多个标签(例如 `VFX_HitSpark` 同时有 `Poolable` 标签)
- 新增标签前确认是否有批量加载的需求,避免标签膨胀
- 一个资产可附加多个标签(例如 `VFX_HitSpark` 同时有 `Poolable``Preload` 标签)
- 新增标签前确认是否有批量加载的实际需求,避免标签膨胀(决策流程见 `AddressablesLabelSpec.md §6`
### 8.4 AddressKeys.cs 维护流程