# 资源文件夹目录规划与管理规范 > **版本**:1.3 > **创建日期**:2026-05 > **适用范围**:`Assets/` 目录下所有非代码资源(美术、数据、预制体、场景等) > **资源管理系统**:Unity Addressables(禁止使用 `Resources.Load`) > **关联文档**:`Architecture/01_ProjectStructure.md`、`Architecture/13_AssetPoolModule.md` --- ## 目录 1. [为什么使用 `_Game/` 父目录](#0-为什么使用-_game-父目录) 2. [整体目录结构总览](#1-整体目录结构总览) 3. [Art/ 美术资源规范](#2-art-美术资源规范) 4. [Data/ ScriptableObject 规范](#3-data-scriptableobject-规范) 5. [Prefabs/ 预制体规范](#4-prefabs-预制体规范) 6. [Scenes/ 场景规范](#5-scenes-场景规范) 7. [Shaders/ 着色器规范](#6-shaders-着色器规范) 8. [UI Toolkit/ 规范](#7-ui-toolkit-规范) 9. [Addressables 管理规范](#8-addressables-管理规范) 10. [Import Settings 规范](#9-import-settings-规范) 11. [资源新增工作流](#10-资源新增工作流) 12. [禁止行为清单](#11-禁止行为清单) 13. [编辑器工具参考](#12-编辑器工具参考) --- ## 0. 为什么使用 `_Game/` 父目录 ### 核心矛盾 Unity 项目的 `Assets/` 根目录通常同时存放**第一方游戏内容**和**第三方插件目录**。两者混杂会导致: - Project 窗口难以快速定位自有资产(需要在 `Art/`、`Feel/`、`Opsive/` 之间来回跳转) - 插件升级时不清楚哪些目录是项目本身的 - 构建分析工具(如 Addressables Analyze、Build Layout)的输出路径噪音多 ### 解决方案:`_Game/` 父目录 将**所有第一方资产**归入 `Assets/_Game/`,下划线前缀使其在字母排序中始终置顶。 ``` Assets/ ├── _Game/ ← 所有第一方资产(Art、Data、Prefabs、Scenes、Scripts 等) │ ├── AddressableAssetsData/ ← Unity 托管,必须保持在 Assets/ 根 ├── Feel/ ← 第三方(只读) ├── Opsive/ ← 第三方(只读) ├── PathBerserker2d/ ← 第三方(只读) ├── Plugins/ ← 第三方(只读) └── Tests/ ← 测试(可独立于 _Game/) ``` ### 迁移注意事项 | 项目 | 说明 | |------|------| | `AddressableAssetsData/` | **必须留在 `Assets/` 根目录**,Unity Addressables 硬编码此路径 | | `Settings/` | URP asset、Input Actions 等 Unity 项目设置文件可随 `_Game/` 迁移 | | `Resources/` | 如存在,应逐步清空并删除;过渡期可临时留在根目录 | | `StreamingAssets/` | 必须留在 `Assets/` 根目录(Unity 特殊文件夹) | | asmdef 路径 | 迁移 `Scripts/` 后需在 Unity 中重新扫描,asmdef 引用由 GUID 追踪,路径变更不影响依赖 | --- ## 1. 整体目录结构总览 ``` Assets/ ├── _Game/ ← 所有第一方游戏资产 │ ├── Art/ 美术源文件(Sprites、Animations、Materials、Atlases) │ │ ├── Characters/ 角色美术(玩家 / 敌人 / NPC) │ │ │ ├── Player/ 按形态 ID 分子目录(Player01、Player02…) │ │ │ ├── Enemies/ 按敌人 ID 分子目录(E001、E002…) │ │ │ └── NPCs/ 非战斗 NPC,按角色名分子目录 │ │ ├── Environment/ 场景环境(Tilesets、Backgrounds、Props) │ │ ├── Effects/ 特效美术(Sprites、Materials、Atlases) │ │ ├── UI/ UI 专用图片(Icons、Frames、Backgrounds、Atlases、Materials) │ │ │ ├── Icons/ │ │ │ │ ├── Skills/ 技能图标 │ │ │ │ ├── Items/ 道具 / 护身符图标 │ │ │ │ ├── Status/ 状态效果图标 │ │ │ │ └── InputKeys/ 按键/手柄按键图标(供 InputDeviceIconSetSO 引用) │ │ │ ├── Frames/ │ │ │ ├── Backgrounds/ │ │ │ └── Atlases/ │ │ └── Shared/ 跨模块复用基础资产(Palettes、Textures、Materials) │ │ │ ├── Data/ ScriptableObject 资产(按模块分类) │ │ ├── Events/ 事件频道 SO(按模块分子目录) │ │ ├── Player/ │ │ ├── Combat/ │ │ ├── Enemies/ │ │ ├── Progression/ │ │ ├── Audio/ │ │ ├── World/ │ │ ├── UI/ │ │ │ ├── Panels/ UI 面板配置 SO │ │ │ └── InputIcons/ 按键图标集 SO(InputDeviceIconSetSO,每设备一个文件) │ │ └── Settings/ │ │ │ ├── Prefabs/ 预制体 │ │ ├── Player/ │ │ ├── Enemies/ │ │ ├── Combat/ │ │ ├── Effects/ │ │ ├── Environment/ 场景骨架结构(Tilemap 层、视差背景层) │ │ ├── World/ │ │ ├── UI/ │ │ └── Persistent/ Persistent 场景专属 Prefabs │ │ │ ├── Scenes/ 场景文件 │ │ └── Testings/ 测试专用场景(不进入 Addressables 构建) │ │ │ ├── Scripts/ 游戏代码(见 Architecture/01_ProjectStructure.md) │ │ │ ├── Shaders/ 自定义着色器 & HLSL include │ │ ├── BaseASE/ Shader Graph / ASE 材质图 │ │ └── Includes/ 共享 HLSL 函数库(ColorUtils、NoiseUtils 等) │ │ │ ├── UI Toolkit/ UITK 资产(UXML、USS、主题) │ │ ├── Layouts/ │ │ ├── Styles/ │ │ └── UnityThemes/ │ │ │ └── Settings/ URP 配置、Input Actions 等项目设置资产 │ ├── AddressableAssetsData/ ← Unity 托管,必须在 Assets/ 根(不可移动) ├── StreamingAssets/ ← Unity 特殊文件夹(如有 FMOD bank) ├── Feel/ ← MoreMountains Feel 插件(只读) ├── Opsive/ ← Behavior Designer 插件(只读) ├── PathBerserker2d/ ← 寻路插件(只读) ├── Plugins/ ← 其他第三方插件(只读) └── Tests/ ← EditMode / PlayMode 测试(可在 _Game/ 外独立维护) ``` > **强制约束**:`AddressableAssetsData/` 和 `StreamingAssets/` 是 Unity 硬编码路径,**永远不得移入 `_Game/`**。所有第三方插件目录**不修改内部结构**,定制内容一律放入 `_Game/` 下的对应模块目录。 --- ## 2. Art/ 美术资源规范 ### 2.1 目录结构 ``` Art/ ├── Characters/ 角色美术资产(玩家 / 敌人 / NPC) │ ├── Player/ 玩家角色,按形态 ID 分子目录 │ │ └── {FormID}/ 例:Player01、Player02 │ │ ├── Sprites/ 像素帧图 (.png) + Emission 自发光贴图,PPU=32, Filter=Point · PLY_{FormID}_{Action}.png │ │ ├── Animations/ 动作片段 (.anim) + 状态机控制器 (.controller),12fps · {Action}.anim / PLY_{FormID}_Animator.controller │ │ ├── Materials/ 渲染材质 (.mat),引用角色 Shader(控制 Emission、受击闪白参数)· PLY_{FormID}.mat │ │ └── Atlases/ Sprite 图集 (.spriteatlas),合并同形态所有帧,减少 DrawCall · Atlas_Player_{FormID}.spriteatlas │ ├── Enemies/ 敌人,按 ID 分子目录(ID 与 AddressKeys ENM_ 前缀对应) │ │ └── {EnemyID}/ 例:E001、E002 │ │ ├── Sprites/ 像素帧图 (.png) + Emission 贴图,PPU=32 · {ID}_{Name}_{Action}.png │ │ ├── Animations/ 动作片段 (.anim) + 状态机控制器 (.controller) · {Action}.anim / {ID}_{Name}_Animator.controller │ │ ├── Materials/ 渲染材质 (.mat),引用角色 Shader · {ID}.mat │ │ └── Atlases/ Sprite 图集 (.spriteatlas),含主体与 Emission 帧 · Atlas_Enemy_{ID}.spriteatlas │ └── NPCs/ 非战斗 NPC,按角色名分子目录 │ └── {NPCName}/ │ ├── Sprites/ 像素帧图 (.png) · {NPCName}_{Action}.png │ ├── Animations/ 动作片段 (.anim) + 状态机控制器 (.controller) · {Action}.anim / {NPCName}_Animator.controller │ ├── Materials/ 渲染材质 (.mat) · NPC_{NPCName}.mat │ └── Atlases/ Sprite 图集 (.spriteatlas) · Atlas_NPC_{NPCName}.spriteatlas ├── Environment/ 场景环境资产 │ ├── Tilesets/ 瓦片纹理 (.png),配合 RuleTile 实现地形自动拼接 │ │ └── {Region}/ 按区域分子目录(例:Forest、Dungeon、Cave)· TILE_{Region}_{Name}.png │ ├── Backgrounds/ 视差滚动背景图 (.png),按 Far / Mid / Near 分层渲染 │ │ └── {Region}/ 按区域分子目录 · BG_{Region}_{Layer}.png │ └── Props/ 可复用场景道具纹理(箱子、灯柱、机关等,无逻辑纯视觉) │ └── {Category}/ 按类别分子目录(例:Furniture、Traps、Lights)· PROP_{Category}_{Name}.png ├── Effects/ 特效美术资产(Prefab 见 Prefabs/Effects/,此处仅存源图与材质) │ ├── Sprites/ VFX 帧序列图 (.png),PPU=32,用于粒子 / 帧动画特效 · VFX_{Description}.png │ ├── Materials/ 特效专用材质 (.mat),引用 Effects Shader(支持扭曲、混合)· VFX_{Description}.mat │ └── Atlases/ 高频特效 Sprite 图集 (.spriteatlas),减少特效渲染批次 · Atlas_Effects_{Name}.spriteatlas ├── UI/ UI 专用图片(布局 / 样式见 UI Toolkit/ 目录) │ ├── Icons/ 图标按子类分目录,统一 32x32 或 64x64 规格 │ │ ├── Skills/ 技能图标,用于技能栏 / 技能选择界面 · IC_Skills_{Name}.png │ │ ├── Items/ 道具 / 护身符图标,用于物品栏 · IC_Items_{Name}.png │ │ ├── Status/ 状态效果图标(中毒、燃烧等),用于角色状态栏 · IC_Status_{Name}.png │ │ └── InputKeys/ 按键/手柄按键图标,用于 InputDeviceIconSetSO 绑定路径图标映射 · IC_Key_{DeviceShort}_{KeyName}.png │ ├── Frames/ 面板框架、血条框、对话框边框等 (.png) · FRAME_{Description}.png │ ├── Backgrounds/ 界面背景图、全屏半透明遮罩、渐变填充图 (.png) · UIBG_{Description}.png │ └── Atlases/ UI 图标与框架图集 (.spriteatlas),减少 UI 渲染批次 · Atlas_UI_{Category}.spriteatlas └── Shared/ 跨模块复用的基础资产,不属于任何具体角色或场景 ├── Palettes/ 色板参考文件 (.png / .aco),仅供美术设计参考,不用于运行时 └── Textures/ 通用基础纹理:噪点图、渐变纹理、光晕贴图,供 Shader 采样使用 ``` ### 2.2 美术文件命名规则 | 资产类型 | 存放位置 | 命名格式 | 示例 | |---------|---------|---------|------| | 敌人 Sprite Sheet | `_Game/Art/Characters/Enemies/{EnemyID}/Sprites/` | `{ID}_{Name}_{Action}.png` | `E001_CaoZhi_Idle.png` | | 敌人 Emission 贴图 | `_Game/Art/Characters/Enemies/{EnemyID}/Sprites/` | `{ID}_{Name}_{Action}_Emission.png` | `E001_CaoZhi_Idle_Emission.png` | | 敌人 AnimationClip | `_Game/Art/Characters/Enemies/{EnemyID}/Animations/` | `{Action}.anim` | `Idle.anim`、`Skill_Start.anim` | | 敌人 AnimatorController | `_Game/Art/Characters/Enemies/{EnemyID}/Animations/` | `{ID}_{Name}_Animator.controller` | `E001_CaoZhi_Animator.controller` | | 敌人材质 | `_Game/Art/Characters/Enemies/{EnemyID}/Materials/` | `{ID}.mat` | `E001.mat` | | 玩家 Sprite Sheet | `_Game/Art/Characters/Player/{FormID}/Sprites/` | `PLY_{FormID}_{Action}.png` | `PLY_Player01_Run.png` | | 玩家 AnimationClip | `_Game/Art/Characters/Player/{FormID}/Animations/` | `{Action}.anim` | `Idle.anim`、`Attack01.anim` | | 玩家材质 | `_Game/Art/Characters/Player/{FormID}/Materials/` | `PLY_{FormID}.mat` | `PLY_Player01.mat` | | 特效 Sprite Sheet | `_Game/Art/Effects/Sprites/` | `VFX_{Description}.png` | `VFX_HitSpark_Sheet.png` | | 特效材质 | `_Game/Art/Effects/Materials/` | `VFX_{Description}.mat` | `VFX_HitSpark.mat` | | 瓦片纹理 | `_Game/Art/Environment/Tilesets/{Region}/` | `TILE_{Region}_{Name}.png` | `TILE_Forest_Ground.png` | | 背景层 | `_Game/Art/Environment/Backgrounds/{Region}/` | `BG_{Region}_{Layer}.png` | `BG_Forest_Far.png` | | 场景道具 | `_Game/Art/Environment/Props/{Category}/` | `PROP_{Category}_{Name}.png` | `PROP_Furniture_Chest.png` | | UI 图标 | `_Game/Art/UI/Icons/{SubType}/` | `IC_{Category}_{Name}.png` | `IC_Skills_SoulBlade.png` | | 按键图标 | `_Game/Art/UI/Icons/InputKeys/` | `IC_Key_{DeviceShort}_{KeyName}.png` | `IC_Key_KBM_Space.png`、`IC_Key_Xbox_A.png` | | UI 框架 | `_Game/Art/UI/Frames/` | `FRAME_{Description}.png` | `FRAME_HealthBar.png` | | UI 背景 | `_Game/Art/UI/Backgrounds/` | `UIBG_{Description}.png` | `UIBG_PauseMenu.png` | | 色板参考 | `_Game/Art/Shared/Palettes/` | `PAL_{Name}.png` | `PAL_Forest.png` | ### 2.3 Sprite Atlas 策略 | Atlas 文件 | 覆盖内容 | 存放位置 | |-----------|---------|--------| | `Atlas_Player_{FormID}.spriteatlas` | 该形态玩家所有 Sprite | `_Game/Art/Characters/Player/{FormID}/Atlases/` | | `Atlas_Enemy_{EnemyID}.spriteatlas` | 该敌人所有 Sprite(含 Emission)| `_Game/Art/Characters/Enemies/{EnemyID}/Atlases/` | | `Atlas_NPC_{NPCName}.spriteatlas` | 该 NPC 所有 Sprite | `_Game/Art/Characters/NPCs/{NPCName}/Atlases/` | | `Atlas_Effects_Common.spriteatlas` | 通用高频特效 Sprite | `_Game/Art/Effects/Atlases/` | | `Atlas_UI_Icons.spriteatlas` | 所有 UI 图标(技能/道具/状态)| `_Game/Art/UI/Atlases/` | | `Atlas_UI_Frames.spriteatlas` | 面板框架、血条框等 | `_Game/Art/UI/Atlases/` | **规则**: - Atlas 文件放在**被打包 Sprite 的同目录下的 `Atlases/` 子文件夹**,而非集中到单独目录 - **Atlas 本身不注册 Addressable**,通过所属 Prefab/Material 间接引用,由 Unity 自动处理依赖 - 区域特有的敌人或环境资产可单独建 Atlas,避免跨区域 Atlas 导致整体加载 - Atlas 内不混入不同生命周期的资产(例如:角色 Sprite 与 UI 图标不合并) --- ## 3. Data/ ScriptableObject 规范 ### 3.1 完整目录结构 ``` Data/ ├── Events/ 所有事件频道 SO(每个事件独立一个文件) │ ├── Core/ 游戏状态、场景加载等核心事件 │ ├── Player/ 玩家相关事件 │ ├── Combat/ 战斗相关事件 │ ├── Enemies/ 敌人相关事件 │ ├── World/ 世界交互事件(含 EVT_ShowInteractPrompt、EVT_HideInteractPrompt) │ ├── UI/ UI 显隐事件(含 EVT_InputDeviceChanged) │ ├── Audio/ 音频播放事件 │ ├── Progression/ 进度成长事件 │ ├── Dialogue/ 对话事件 │ ├── Quest/ 任务事件 │ ├── Boss/ Boss 相关事件 │ └── Difficulty/ 难度调整事件 ├── Player/ │ ├── Forms/ 各形态配置 │ └── Input/ 输入配置 ├── Combat/ │ ├── DamageSources/ 伤害源配置 │ └── Weapons/ 武器配置 ├── Enemies/ │ └── {EnemyID}/ 每个敌人的数据目录 ├── Progression/ │ ├── Skills/ 技能配置 │ ├── Spells/ 法术配置 │ ├── Charms/ 护身符配置 │ └── Abilities/ 能力配置 ├── Audio/ │ ├── BGM/ 背景音乐配置 │ └── SFX/ 音效配置 ├── World/ │ ├── Map/ 地图与房间配置 │ └── Shop/ 商店配置 ├── UI/ │ ├── Panels/ UI 面板配置 │ └── InputIcons/ 按键图标集 SO(每设备一个文件,通过 Inspector 直接引用,不走 Addressables) └── Settings/ 全局设置与难度配置 ``` ### 3.2 SO 资产命名规则 格式:`{SystemPrefix}_{描述}.asset`,参考 `Architecture/01_ProjectStructure.md §3` 前缀表。 | 前缀 | 系统 | 示例 | |------|------|------| | `EVT_` | 事件频道 | `EVT_PlayerDied.asset` | | `PLY_` | 玩家 | `PLY_PlayerStats.asset` | | `CMB_` | 战斗 | `CMB_DamageSource_Sword.asset` | | `ENM_` | 敌人 | `ENM_E001_Stats.asset` | | `WPN_` | 武器 | `WPN_SkyBlade.asset` | | `SKL_` | 技能/法术 | `SKL_SoulBlade.asset` | | `SPL_` | 法术(Spell) | `SPL_Fireball.asset` | | `CHM_` | 护身符 | `CHM_GhostMantis.asset` | | `SHP_` | 商店 | `SHP_Inventory_Forest.asset` | | `MAP_` | 地图 | `MAP_RoomData_Forest_01.asset` | | `AUD_` | 音频 | `AUD_BGMPlaylist_Forest.asset` | | `UI_` | UI 配置 | `UI_PanelConfig_HUD.asset` | | `SET_` | 设置 | `SET_GlobalSettings.asset` | | `ABL_` | 能力 | `ABL_DoubleJump.asset` | | `ICN_` | 按键图标集 | `ICN_KeyboardMouse.asset`、`ICN_Xbox.asset` | ### 3.3 事件频道 SO 特别规则 - 每个事件频道**独立一个文件**,禁止在同一 `.cs` 脚本中定义多个频道类(防止 Script 引用丢失) - 文件名与类型名严格对应:`EVT_PlayerDied.asset` 对应 `PlayerDiedEventChannelSO` - **事件频道 SO 不注册 Addressable**,通过 Inspector 直接引用 --- ## 4. Prefabs/ 预制体规范 ### 4.1 目录结构 ``` Prefabs/ ├── Player/ 玩家顶级 Prefab,含控制器 / 动画 / 碰撞体(Addressable:PLY_Player)· PLY_Player.prefab ├── Enemies/ │ └── {EnemyID}/ 敌人顶级 Prefab,含 AI 行为树 / 动画 / 碰撞体(Addressable:ENM_{Name})· ENM_{Name}.prefab ├── Combat/ │ ├── HitBox/ 主动攻击碰撞盒,嵌套于角色 Prefab 内,随角色一同打包,不单独注册 Addressable │ ├── HurtBox/ 受击判定盒,同上规则,不单独注册 Addressable │ └── Projectiles/ 抛射物顶级 Prefab,独立实例化,纳入对象池(标签 Poolable)· PROJ_{Name}.prefab ├── Effects/ 特效顶级 Prefab(粒子系统 / 帧动画),纳入对象池,标签 Poolable · VFX_{Name}.prefab ├── Collectibles/ 可收集物件(灵魂碎片、道具、恢复球),纳入对象池,标签 Poolable · COL_{Name}.prefab├── Environment/ 场景骨架结构 Prefab,由关卡场景直接引用,不注册 Addressable │ ├── Tilemaps/ Tilemap 层 GameObject Prefab,含 Grid / TilemapRenderer / Collider2D,每种地形层独立一个 Prefab · ENV_Tilemap_{Layer}.prefab │ └── Backgrounds/ 视差滚动背景层 Prefab,含 SpriteRenderer + ParallaxScroller,每区域按 Far / Mid / Near 分层 · ENV_BG_{Region}_{Layer}.prefab├── World/ │ ├── Interactables/ 场景可交互物件(宝箱、NPC 对话触发器、传送门),含交互逻辑组件 · WLD_{Name}.prefab │ ├── Traps/ 机关陷阱(刺、摆锤、喷火),含周期性伤害触发逻辑 · WLD_{Name}.prefab │ └── Props/ 纯视觉场景道具(无逻辑),用于场景布景装饰 · WLD_{Name}.prefab ├── UI/ UI 面板顶级 Prefab,由 UIManager 通过 Addressable 实例化(组:UI)· UI_{PanelName}.prefab └── Persistent/ 持久场景全局管理器,随 Persistent 场景加载,全程不销毁 · SYS_{ManagerName}.prefab ``` ### 4.2 Prefab 命名规则 | 类型 | 前缀 | 示例 | |------|------|------| | 玩家 | `PLY_` | `PLY_Player.prefab` | | 敌人 | `ENM_` | `ENM_GruntWarrior.prefab` | | 抛射物 | `PROJ_` | `PROJ_Arrow.prefab` | | 特效 | `VFX_` | `VFX_HitSpark.prefab` | | UI | `UI_` | `UI_HUD.prefab` | | 收集物 | `COL_` | `COL_HPOrb.prefab` | | 世界物件 | `WLD_` | `WLD_Torch.prefab` | | 武器 | `WPN_` | `WPN_SkyBlade.prefab` | | 持久对象 | `SYS_` | `SYS_GameManager.prefab` | | 环境结构 | `ENV_` | `ENV_Tilemap_Ground.prefab`、`ENV_BG_Forest_Far.prefab` | ### 4.3 Prefab 嵌套规则 - Prefab 内的子物件(HitBox、HurtBox、骨骼节点)**不单独注册 Addressable** - 武器 Prefab 嵌套在角色 Prefab 内时,通过 Nested Prefab 引用,不用 Addressables 动态加载 - 只有**顶级可实例化对象**才注册 Addressable 地址 --- ## 5. Scenes/ 场景规范 ### 5.1 目录结构 ``` Scenes/ ├── Persistent.unity 常驻场景,承载全局管理器 Prefab(GameManager / AudioManager / UIManager),永不卸载 ├── MainMenu.unity 主菜单场景,游戏启动后首先加载,含主题音乐与过场动画 ├── Room_{Region}_{Index:D2}.unity 普通关卡房间,含静态地形与区域触发器(敌人 / 道具由 Spawner 动态实例化)· 例:Room_Forest_01.unity ├── Boss_{Name}.unity Boss 专属战斗场景,含专属 BGM、Boss AI 与阶段触发逻辑 · 例:Boss_CaoZhi.unity └── Testings/ 开发测试专用场景,不注册 Addressable,不进入正式构建流程 ``` ### 5.2 场景命名规则 | 类型 | 命名格式 | Addressable 地址 | |------|---------|----------------| | 常驻场景 | `Persistent.unity` | `Scene_Persistent` | | 主菜单 | `MainMenu.unity` | `Scene_MainMenu` | | 关卡房间 | `Room_{Region}_{Index:D2}.unity` | `Room_Forest_01` | | Boss 战 | `Boss_{Name}.unity` | `Boss_CaoZhi` | | 测试场景 | 任意(在 Testings/) | **不注册 Addressable** | ### 5.3 场景内容规范 - **Persistent 场景**:只放全局管理器 Prefab(`SYS_GameManager`、`SYS_AudioManager`、`SYS_UIManager`),其余全部通过 Addressables 动态加载 - **关卡场景**:只放该关卡的静态地形与触发器;角色、敌人由 Spawner 通过 Addressables 实例化 - 禁止在场景中直接拖拽引用 `Prefabs/` 下的动态对象(改用 Spawner + Addressable Key) --- ## 6. Shaders/ 着色器规范 ### 6.1 目录结构 ``` _Game/Shaders/ ├── BaseASE/ Shader Graph 图,每个文件对应一个渲染目的,不合并不相关效果 · {Category}_{Purpose}.shadergraph │ ├── Character/ 角色类:主材质(Emission 自发光 + 受击闪白参数)、描边、溶解 / 死亡效果 │ ├── Environment/ 环境类:Tilemap 地形着色、多层视差背景、水面 / 液体流动效果 │ ├── Effects/ 特效类:VFX Sprite 通用(Alpha 混合 + 颜色偏移)、热浪扭曲 │ └── UI/ UI 类:默认 UI 渲染、灰度效果(用于禁用状态的技能 / 道具图标) └── Includes/ 跨 Shader 共享 HLSL 函数库,通过相对路径 #include 引用 · {FunctionGroup}.hlsl ``` ### 6.2 Shader 命名规则 | 类型 | 命名格式 | 示例 | |------|---------|------| | Shader Graph | `{Category}_{Purpose}.shadergraph` | `Character_Main.shadergraph` | | HLSL include | `{FunctionGroup}.hlsl` | `ColorUtils.hlsl` | | Shader Variant Collection | `SVC_{Category}.shadervariants` | `SVC_Characters.shadervariants` | ### 6.3 Shader 管理规则 - Shader 资产**不注册 Addressable**,由 Material 直接引用,Material 随 Prefab 打包 - HLSL include 文件放在 `Shaders/Includes/`,使用**相对路径** `#include` 引用 - 每个渲染目的对应一个 `.shadergraph`,**不合并多个不相关效果到同一 Graph** - Shader 变体数量需受控:通过 `Shader Variant Collection` 预热,避免运行时卡顿 --- ## 6.5 Material 管理规范 ### 6.5.1 Material 存放原则 Material(`.mat`)**紧邻使用它的资产存放**,不设全局集中目录: | 使用对象 | Material 存放位置 | 命名格式 | 示例 | |---------|----------------|---------|------| | 玩家角色 | `_Game/Art/Characters/Player/{FormID}/Materials/` | `PLY_{FormID}.mat` | `PLY_Player01.mat` | | 敌人 | `_Game/Art/Characters/Enemies/{EnemyID}/Materials/` | `ENM_{ID}.mat` | `ENM_E001.mat` | | NPC | `_Game/Art/Characters/NPCs/{NPCName}/Materials/` | `NPC_{Name}.mat` | `NPC_Merchant.mat` | | 特效 VFX | `_Game/Art/Effects/Materials/` | `VFX_{Description}.mat` | `VFX_HitSpark.mat` | | 环境/Tilemap | `_Game/Art/Environment/Tilesets/{Region}/Materials/` | `TILE_{Region}_{Name}.mat` | `TILE_Forest_Ground.mat` | | 环境背景 | `_Game/Art/Environment/Backgrounds/{Region}/Materials/` | `BG_{Region}.mat` | `BG_Forest.mat` | | 场景道具 | `_Game/Art/Environment/Props/{Category}/Materials/` | `PROP_{Name}.mat` | `PROP_Chest.mat` | | UI 专用 | `_Game/Art/UI/Materials/` | `UI_{Description}.mat` | `UI_HealthBar.mat` | | 共享/通用 | `_Game/Art/Shared/Materials/` | `MAT_{Description}.mat` | `MAT_Dissolve.mat` | ### 6.5.2 Material 命名规则 - 同一对象有多个 Material 时加 `_{Variant}` 后缀区分: - `ENM_E001.mat`(主材质) - `ENM_E001_Emission.mat`(发光变体,若需要单独材质) - `ENM_E001_Flash.mat`(受击闪白材质,通过代码切换) - Emission 贴图与主贴图共享同一 Material,通过 Shader 属性 `_EmissionMap` 关联,**无需单独 Material** - 受击闪白效果推荐通过 Shader 属性(如 `_FlashAmount`)在运行时控制,避免 Material 实例爆炸 ### 6.5.3 Material 实例化规则 ```csharp // ✅ 推荐:通过 MaterialPropertyBlock 修改,不产生 Material 实例 var mpb = new MaterialPropertyBlock(); mpb.SetFloat("_FlashAmount", 1f); renderer.SetPropertyBlock(mpb); // ⚠ 避免:直接修改 renderer.material(每次调用都创建新实例,造成内存泄漏) renderer.material.SetFloat("_FlashAmount", 1f); // ⚠ 产生实例 // ✅ 允许:需要持久独立状态时显式用 Instantiate,并在 OnDestroy 中手动 Destroy _matInstance = Instantiate(renderer.sharedMaterial); renderer.material = _matInstance; // ... OnDestroy: Destroy(_matInstance); ``` --- ## 7. UI Toolkit/ 规范 ``` UI Toolkit/ ├── PanelSettings.asset 面板渲染配置(Scale Mode、Sort Order、Reference Resolution),全局唯一,不得创建多个 ├── UnityThemes/ Unity 编辑器内置主题文件,不修改 ├── Layouts/ UXML 布局文件,每个面板对应一个文件,与 Prefabs/UI/ 同名 · {PanelName}.uxml └── Styles/ USS 样式表:Variables.uss(全局 CSS 变量)、Common.uss(通用控件样式)、{PanelName}.uss(面板专属样式) ``` - `PanelSettings.asset` 全局唯一,不得创建多个 - UXML 和 USS 按界面功能命名,与对应的 `Prefabs/UI/` 同名 --- ## 8. Addressables 管理规范 ### 8.1 分组(Group)划分策略 | 组名 | 包含内容 | Build 类型 | 加载时机 | |------|---------|-----------|---------| | `Default Local Group` | 常驻 Prefab(GameManager、UIManager 等)、全局配置 SO | Local | 启动时自动加载 | | `UI` | 所有 UI Prefab(HUD、菜单、弹框等) | Local | 启动时预加载 | | `Player` | 玩家 Prefab、武器 Prefab | Local | 游戏开始时加载 | | `VFX_Common` | 通用高频特效(HitSpark、BloodSplat 等) | Local | 启动时预加载 | | `Collectibles` | 收集物 Prefab(Geo、Item、HPOrb) | Local | 启动时预加载 | | `Projectiles` | 抛射物 Prefab | Local | 启动时预加载 | | `Enemies` | 所有敌人 Prefab(`ENM_*`) | Local | 进入区域时加载 | | `Room_{Region}` | 该区域的关卡场景 + 区域专属资产 | Local | 进入区域时加载 | | `Boss_{Name}` | Boss 专属 Prefab + 场景 | Local | Boss 战开始前加载 | | `Audio_Music` | BGM 音频(FMOD bank 引用) | Remote(可选)| 按需流式加载 | | `Config` | 运行时需要动态加载的配置 SO | Local | 按需加载 | **划分原则**: 1. **生命周期相同的资源放同一组**——一起加载、一起卸载 2. **不同区域的资源绝对隔离**——防止 Region A 的资产随 Region B 打包 3. **高频小资产合入 Common 组**——避免大量小 handle 的运行时开销 4. **场景文件与其依赖资产放同一组**——确保 SceneManager 加载时依赖已在本地 ### 8.2 Address 命名规则 地址字符串格式:`{SystemPrefix}_{描述}` 或 `{Category}/{描述}` ``` # Prefab 类(无路径前缀) PLY_Player ENM_GruntWarrior ENM_SkullArcher PROJ_Arrow VFX_HitSpark UI_HUD COL_HPOrb # 场景类 Scene_Persistent Scene_MainMenu Room_Forest_01 Boss_CaoZhi # 配置数据类(带路径前缀区分) Config/FootstepCatalog Config/DifficultyEasy ``` **强制要求**:所有 Address 必须在 `AddressKeys.cs` 中定义对应常量,**禁止在代码中硬编码字符串**。 ### 8.3 Label(标签)使用规范 > 完整定义见 `Standards/AddressablesLabelSpec.md`。 | 标签 | 用途 | 相关常量 | |------|------|---------| | `Preload` | 游戏启动时通过 `DownloadDependenciesAsync` 预热下载依赖 | `AddressKeys.Labels.Preload` | | `Poolable` | 纳入 `GlobalObjectPool` 对象池管理的 Prefab(VFX、投射物、收集物等)| `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` 和 `Preload` 标签) - 新增标签前确认是否有批量加载的实际需求,避免标签膨胀(决策流程见 `AddressablesLabelSpec.md §6`) ### 8.4 AddressKeys.cs 维护流程 文件路径:`Assets/_Game/Scripts/Core/Assets/AddressKeys.cs` **工作流(添加新资产)**: ``` 1. 在 Project 中创建/导入资产 2. 在 AddressKeys.cs 中添加对应 const 字符串 3. 在 AddressableBatchTool(菜单 `BaseGames/Addressables/Addressable Batch Tool`)中: a. 切换到 "① 同步 AddressKeys" 标签 b. 点击 "Scan" 找到未注册的 Key c. 选择目标 Group,点击 "Register" 完成注册 4. 运行 AddressKeyValidator(菜单 `BaseGames/Addressables/Validate Address Keys`) 确认无 Missing / Mismatch 警告 5. 提交 AddressKeys.cs 和 AddressableAssetSettings.asset 的修改 ``` **工作流(删除/重命名资产)**: ``` 1. 先在 AddressKeys.cs 中删除/修改对应常量 2. 全局搜索该常量的所有引用并更新 3. 在 Addressables Groups 窗口手动删除或重命名对应条目 4. 重新运行 AddressKeyValidator 验证 5. 提交所有修改(.cs + .asset 文件) ``` ### 8.5 AssetLoader 使用规范 封装类路径:`Assets/_Game/Scripts/Core/Assets/AssetLoader.cs` ```csharp // ✅ 正确:使用 AssetLoader + AddressKeys 常量 var (prefab, handle) = await AssetLoader.LoadAsync(AddressKeys.PrefabPlayer); _tracker.Track(handle); // 注册到 AssetReleaseTracker,场景卸载时自动 Release // ✅ 正确:对象池中不直接 Release,由池管理器统一处理 // ❌ 禁止:直接调用 Addressables API(绕过封装层) var handle = Addressables.LoadAssetAsync("PLY_Player"); // ❌ // ❌ 禁止:加载后不 Release(内存泄漏) var (prefab, _) = await AssetLoader.LoadAsync(AddressKeys.PrefabPlayer); // ❌ 忘记 Track ``` ### 8.6 加载/释放生命周期 ``` 场景加载时: SceneManager 激活 → 场景根 GO 上挂 AssetReleaseTracker → 各 Spawner/Manager 调用 AssetLoader.LoadAsync → Track handle 场景卸载时: AsyncOperation.completed → AssetReleaseTracker.OnDestroy 自动 Release 所有 handle → 内存归零(无需手动清理) 对象池: Pool 持有 handle(不 Track 到 AssetReleaseTracker) → Pool 销毁时显式 Release(Pool 自身管理生命周期) ``` ### 8.7 Build 策略 | 构建目标 | 命令 | 说明 | |---------|------|------| | 开发测试 | `Build > New Build > Default Build Script` | 全量本地构建,输出到 `Library/com.unity.addressables/` | | 内容更新 | `Build > Update a Previous Build` | 仅重打修改的 Group,需保留上次 catalog | | 生产发布 | CI 流水线触发全量构建 | Remote Group 上传 CDN,Local Group 打入安装包 | **注意**:`AddressableAssetsData/` 目录下的文件由 Unity 自动维护,**不得手动修改 .asset 内容**,只通过 Addressables Groups 窗口操作。 --- ## 9. Import Settings 规范 ### 9.1 Sprite / Texture Import 规范 | 设置项 | 规范值 | 说明 | |-------|-------|------| | Texture Type | `Sprite (2D and UI)` | 角色/特效/UI 图 | | Sprite Mode | `Multiple`(Sprite Sheet)或 `Single` | Sprite Sheet 用 Multiple | | Pixels Per Unit | `32` | 与项目像素密度保持统一 | | Filter Mode | `Point (no filter)` | Pixel Art 项目固定值 | | Compression | `None`(移动平台用 `ASTC 6x6`)| 开发阶段 None,发布时切换 | | Generate Mip Maps | `关闭` | 2D 游戏不需要 Mip Maps | | Read/Write Enabled | `关闭`(除非代码需要像素读写) | 减少内存占用 | | Max Size | 角色 `2048`,UI `1024`,特效 `512` | 按实际尺寸设置上限 | > **Emission 贴图**(`_Emission.png`)使用 **相同 Import 设置**,与主贴图保持一致的 PPU 和 Filter Mode。 ### 9.2 AnimationClip Import 规范 - 直接创建的 `.anim` 文件(非 FBX 内嵌)无需额外 Import 设置 - Loop Time:循环动作(Idle、Move、Skill_Loop)开启;非循环(Death、Hit、Skill_Start)关闭 - Sample Rate:`12` fps(Pixel Art 动画标准帧率) ### 9.3 Audio Import 规范 | 设置项 | SFX | BGM | |-------|-----|-----| | Load Type | `Decompress On Load` | `Streaming` | | Compression Format | `Vorbis` | `Vorbis` | | Quality | `70%` | `60%` | | Load In Background | `关闭` | `开启` | > **注**:若使用 FMOD,Audio 资产由 FMOD Studio 管理,Unity 侧只保留 FMOD Bank 引用 SO,不直接导入 AudioClip。 --- ## 10. 资源新增工作流 ### 10.1 新增敌人 > **推荐工具**:`BaseGames → Data → Enemy Data Manager`(`EnemyDataWindow`)——在左栏点击 [New] 可自动创建 `ENM_*_Stats.asset`,在右栏 Loot Tab 配置掉落表。 ``` 1. _Game/Art/Characters/Enemies/ 下创建 {EnemyID}/ 目录,内含 Sprites/ Animations/ Materials/ Atlases/ 2. 导入 Sprite Sheet 到 Sprites/,配置 Import Settings(PPU=32, Filter=Point, Multiple) 3. 在 Sprite Editor 中切割 Sprite 4. 在 Animations/ 下创建动画片段(.anim)和 Animator Controller 5. 在 Materials/ 下创建材质(引用 _Game/Shaders/ 中的角色 Shader,关联主纹理和 Emission 贴图) 6. 在 Atlases/ 下创建 Atlas_Enemy_{ID}.spriteatlas,包含该敌人所有 Sprite 7. 在 Enemy Data Manager(菜单 BaseGames/Data/Enemy Data Manager)创建 ENM_{ID}_Stats.asset 8. 在 _Game/Prefabs/Enemies/{EnemyID}/ 下创建 ENM_{Name}.prefab 9. 在 AddressKeys.cs 中添加 PrefabEnemy{Name} 常量 10. 使用 Rule Sync(菜单 BaseGames/Addressables/Rule Sync)Scan → Fix All,自动分组并打 Enemy 标签 11. 运行 AddressKeyValidator(菜单 BaseGames/Addressables/Validate Address Keys)验证 ``` ### 10.2 新增武器(Weapon) > **推荐工具**:`BaseGames → Data → Weapon Editor`(`WeaponEditorWindow`)创建 `WPN_*_Data.asset`;`BaseGames → Create → Weapon HitBox Prefab`(`WeaponHitBoxWizard`)创建 4 方向 HitBox Prefab。 ``` 1. 在 _Game/Art/Characters/Player/{FormID}/Sprites/ 下放置武器帧动画 Sprite Sheet,配置 Import Settings 2. 在 Weapon Editor(菜单 BaseGames/Data/Weapon Editor)左栏 [New] 创建 WPN_{Name}_Data.asset - 路径:_Game/Data/Combat/Weapons/WPN_{Name}_Data.asset - 命名:WPN_{Name}(示例:WPN_SkyBlade、WPN_EarthClaw) 3. 使用 Weapon HitBox Wizard(菜单 BaseGames/Create/Weapon HitBox Prefab)生成 _Game/Prefabs/Weapons/WPN_{Name}_HitBox.prefab(自动创建 4 方向 Ground/Up/Down/Air) 4. 在 _Game/Prefabs/Player/ 下创建或更新武器顶级 Prefab WPN_{Name}.prefab 5. 在 AddressKeys.cs 中添加 PrefabWeapon{Name} 常量 6. 使用 Rule Sync 自动分组(Player 组)并打 Weapon + Preload 标签 7. 运行 AddressKeyValidator 验证 ``` ### 10.3 新增技能(Skill) > **推荐工具**:`BaseGames → Data → Skill Editor`(`SkillEditorWindow`)创建 `SKL_*_Data.asset`;`BaseGames → Create → Skill HitBox Prefab`(`SkillHitBoxWizard`)创建多段 HitBox Prefab。 ``` 1. 在 _Game/Art/Characters/Player/{FormID}/Animations/ 下创建技能动画片段(.anim) 2. 在 Skill Editor(菜单 BaseGames/Data/Skill Editor)左栏 [New] 创建 SKL_{SkillID}_Data.asset - 路径:`_Game/Data/Progression/Skills/SKL_{SkillID}_Data.asset` - 命名:SKL_{SkillID}(示例:SKL_DashSlash、SKL_SpiritWave) 3. 使用 Skill HitBox Wizard(菜单 BaseGames/Create/Skill HitBox Prefab)生成 _Game/Prefabs/Skills/SKL_{SkillID}_HitBox.prefab(支持多段伤害配置) 4. 在 AddressKeys.cs 中添加对应常量(如需独立 Addressable 加载) 5. 运行 AddressKeyValidator 验证(如已注册 Addressable) ``` ### 10.4 新增护身符(Charm) > **推荐工具**:`BaseGames → Data → Character Wizard`(切换到 Charm 标签)或直接在 Project 窗口 右键 → Create,使用 `CharmSOEditor`(Custom Inspector)配置,**必须确保路径为 `_Game/Data/Progression/Charms/`,命名为 `CHM_{Name}.asset`**;若护身符类型较多,建议在 §12 中增加专属 Charm Editor 入口以强制规范。 ``` 1. 使用 Character Wizard(菜单 BaseGames/Data/Character Wizard → Charm 标签)创建 CHM_{Name}.asset - 路径:_Game/Data/Progression/Charms/CHM_{Name}.asset - 命名:CHM_{Name}(示例:CHM_SoulReaper、CHM_IronSkin) 2. 在 Inspector 中通过 CharmSOEditor 下拉选择效果类型并配置参数 3. 在 AddressKeys.cs 中添加 DataCharm{Name} 常量 4. 使用 Rule Sync 自动分组(Config 组)并打 Charms 标签 5. 运行 AddressKeyValidator 验证 ``` ### 10.5 新增玩家形态(Player Form) > **推荐工具**:`BaseGames → Tools → Character Wizard`(`CharacterWizardWindow`)统一入口——创建 FormSO、绑定武器引用、跳转到 Form Editor;`BaseGames → Data → Form Editor`(`FormEditorWindow`)进行三魂列阵可视化编辑。 ``` 1. 在 Character Wizard(菜单 BaseGames/Data/Character Wizard)切换到 Player 标签 - 填写 FormID,点击 [Create Form Assets],自动在正确路径创建 FormSO 和相关 SO 2. 在 _Game/Art/Characters/Player/{FormID}/ 下创建 Sprites/ Animations/ Materials/ Atlases/ 目录 3. 导入 Sprite Sheet,配置 Import Settings(PPU=32, Filter=Point, Multiple) 4. 在 Form Editor(菜单 BaseGames/Data/Form Editor)三栏网格中选择形态格位,绑定武器和技能列表 5. 在 _Game/Prefabs/Player/ 下创建 PLY_{FormID}.prefab 6. 在 AddressKeys.cs 中添加 PrefabPlayer{FormID} 常量(如为独立 Addressable) 7. 使用 Rule Sync 自动分组(Player 组)并打 Preload 标签 8. 运行 AddressKeyValidator 验证 ``` ### 10.6 新增 VFX > **提示**:VFX Prefab 必须纳入 `GlobalObjectPool`,在 Pool 配置中指定初始预热数量。 ``` 1. 在 _Game/Art/Effects/Sprites/ 下导入特效 Sprite Sheet,配置 Import Settings(PPU=32, Filter=Point) 2. 在 _Game/Art/Effects/Materials/ 下创建特效材质 3. 在 _Game/Prefabs/Effects/ 下创建 VFX_{Name}.prefab 4. 在 AddressKeys.cs 中添加 PrefabVFX{Name} 常量 5. 使用 Rule Sync 自动分组(VFX_Common 组)并打 Poolable + Preload 标签 6. 在 GlobalObjectPool._warmupConfigs 中添加初始池数量配置 ``` ### 10.7 新增 UI 界面 ``` 1. 在 _Game/UI Toolkit/Layouts/ 下创建 {PanelName}.uxml 2. 在 _Game/UI Toolkit/Styles/ 下创建或复用对应 .uss 3. 在 _Game/Prefabs/UI/ 下创建 UI_{PanelName}.prefab 4. 在 _Game/Data/UI/Panels/ 下创建 UI_PanelConfig_{PanelName}.asset(如需配置 SO) 5. 在 AddressKeys.cs 中添加 PrefabUI{PanelName} 常量 6. 使用 Rule Sync 自动分组(UI 组);常驻全局面板额外打 Preload 标签 ``` ### 10.8 新增关卡场景 ``` 1. 在 _Game/Scenes/ 下创建 Room_{Region}_{Index:D2}.unity 2. 在 AddressKeys.cs 中添加地址常量(复用 SceneRoomPrefix + 动态拼接或新增独立常量) 3. 将场景注册到 Room_{Region} 组(Rule Sync 可自动识别 Room_ 前缀并动态计算组名) 4. 在 _Game/Data/World/Map/ 下创建 MAP_RoomData_{Region}_{Index:D2}.asset ``` ### 10.9 新增输入设备图标集(Input Device Icon Set) > **推荐工具**:`BaseGames/Input Icon Studio`(`InputIconStudioWindow`)——可视化管理所有设备的按键图标,自动写入对应 SO。 **⚠ Addressable 决策:不需要 Addressable。** `InputDeviceIconSetSO` 由 `InputIconService`(挂载在 UIRoot 上)通过 `SerializeField` 直接引用,随常驻场景加载,无需运行时动态加载。 ``` 1. 美术导入 a. 在 _Game/Art/UI/Icons/InputKeys/ 下放置按键图标 Sprite Sheet 或单张 PNG b. Import Settings:Texture Type = Sprite, Filter=Point, PPU=32(像素图)或 PPU=1(矢量/高分辨率图) c. 命名格式:IC_Key_{DeviceShort}_{KeyName}.png DeviceShort:KBM(键鼠)/ Xbox / PS / Switch 示例:IC_Key_KBM_Space.png、IC_Key_Xbox_A.png、IC_Key_PS_Cross.png 2. 创建图标集 SO a. 菜单 BaseGames/Input Icon Studio → 点击对应设备行的「+ 新建」按钮 b. 选择保存路径(推荐 _Game/Data/UI/InputIcons/) c. 命名:ICN_{DeviceType}.asset(例:ICN_KeyboardMouse.asset、ICN_Xbox.asset) 3. 填充图标映射 a. 在 Input Icon Studio 左列选择 Action,右列指定 Sprite(或在 Inspector 的 InputDeviceIconSetSOEditor 中操作) b. 可使用 Inspector 顶部「从 Action Asset 填充路径」按钮批量生成条目,再逐一拖入 Sprite c. 覆盖率芯片变为绿色(100%)表示该设备全部 Action 已配置 4. 绑定到 InputIconService a. 在 Persistent 场景的 UIRoot → InputIconService 组件 Inspector 中 b. 将 4 个 ICN_*.asset 拖入对应 SerializeField 字段(_kbMouseSet / _xboxSet / _playStationSet / _switchSet) 5. 验证 a. 进入 PlayMode,切换输入设备,观察 HUD 交互提示图标是否正确切换 b. 在 Input Icon Studio 的「交互提示预览」中模拟检查各设备外观 ``` **ICN_ SO 命名与路径规则:** | SO 名称 | 路径 | 对应设备 | |---------|------|---------| | `ICN_KeyboardMouse.asset` | `_Game/Data/UI/InputIcons/` | 键鼠(`InputDeviceType.KeyboardMouse`) | | `ICN_Xbox.asset` | `_Game/Data/UI/InputIcons/` | Xbox 手柄(`InputDeviceType.XboxController`) | | `ICN_PlayStation.asset` | `_Game/Data/UI/InputIcons/` | PS4/PS5(`InputDeviceType.PlayStationController`) | | `ICN_Switch.asset` | `_Game/Data/UI/InputIcons/` | Switch Pro/Joy-Con(`InputDeviceType.SwitchController`) | **按键图标命名规范(`IC_Key_{DeviceShort}_{KeyName}.png`):** | 设备简称 | 适用范围 | 示例 | |---------|---------|------| | `KBM` | 键盘按键 / 鼠标按键 | `IC_Key_KBM_Space.png`、`IC_Key_KBM_E.png`、`IC_Key_KBM_LMB.png` | | `Xbox` | Xbox 面板按钮 / 摇杆 / 扳机 | `IC_Key_Xbox_A.png`、`IC_Key_Xbox_RT.png`、`IC_Key_Xbox_LStick.png` | | `PS` | PlayStation 按钮 / 摇杆 / 扳机 | `IC_Key_PS_Cross.png`、`IC_Key_PS_R2.png`、`IC_Key_PS_L1.png` | | `Switch` | Switch 面板按钮 / Joy-Con | `IC_Key_Switch_A.png`、`IC_Key_Switch_ZR.png`、`IC_Key_Switch_DPad.png` | --- ## 11. 禁止行为清单 | 禁止行为 | 原因 | 正确做法 | |---------|------|---------| | `Resources.Load("path")` | 绕过 Addressables,无法热更 | `AssetLoader.LoadAsync(AddressKeys.Xxx)` | | 在代码中硬编码 Address 字符串 | 重构困难,易拼写错误 | 使用 `AddressKeys` 常量 | | 直接调用 `Addressables.LoadAssetAsync` | 绕过封装,难以追踪泄漏 | 使用 `AssetLoader.LoadAsync` | | 加载后不 Release / 不 Track | 内存泄漏 | `_tracker.Track(handle)` 或显式 Release | | 在场景中直接引用动态对象 Prefab | 导致场景与 Prefab 耦合,阻碍动态加载 | Spawner + Addressable Key | | 手动修改 `AddressableAssetsData/*.asset` | 破坏 Addressables 内部状态 | 只通过 Groups 窗口 / AddressableBatchTool 操作 | | 将 Test 场景注册 Addressable | 污染构建内容 | Test 场景放 `Scenes/Testings/` 并排除于所有 Group | | 在同一 Prefab 中跨模块直接引用 SO | 产生跨组依赖,导致资产重复打包 | 通过 Addressables 按需加载配置 SO | | 美术和数据混放在同一目录 | 职责不清,影响构建分析 | 美术在 `_Game/Art/`,数据在 `_Game/Data/`,预制体在 `_Game/Prefabs/` | | 第三方插件目录内创建自定义资产 | 插件升级时被覆盖 | 自定义内容放在 `_Game/` 下对应模块目录 | | 将 `_Game/` 内的资产移到 `Assets/` 根目录 | 破坏第一方/第三方隔离原则 | 所有自有资产必须在 `_Game/` 内 | | 将 `AddressableAssetsData/` 移入 `_Game/` | Unity 硬编码此路径,移动后 Addressables 完全失效 | 永远保留在 `Assets/` 根目录 | | 绕过编辑器工具手动创建 SO / Prefab | 路径或命名不符合规范,导致 Addressables 工具误报 | 使用 §12 中的对应编辑器窗口创建 | --- ## 12. 编辑器工具参考 所有**资产创建**均应通过以下编辑器工具进行,以保证路径、命名、Addressables 注册完全符合本规范。 ### 12.1 资产创建工具 | 工具名称 | 菜单路径 | 负责资产类型 | 说明 | |---------|---------|------------|------| | **Character Wizard** | `BaseGames/Data/Character Wizard` | 角色 SO(玩家形态 / Minion / Boss 通用入口) | 统一入口,自动在正确路径创建所有配套 SO,内含快捷跳转按钮 | | **Form Editor** | `BaseGames/Data/Form Editor` | 玩家三魂形态(FormSO) | 三栏可视化网格,自动绑定武器/技能引用,支持 TianHun / DiHun / MingHun | | **Enemy Data Manager** | `BaseGames/Data/Enemy Data Manager` | 敌人配置 SO(`ENM_*_Stats.asset`)+ 掉落表 | 双面板列表编辑,左栏搜索 + [New],右栏 Stats/Loot 标签 | | **Boss Skill Sequence** | `BaseGames/Data/Boss Skill Sequence` | Boss 技能阶段(BossSkillSO / SkillSequenceSO) | Gantt 时间轴可视化,Windup / Active / Recovery 三段颜色标记 | | **Skill Editor** | `BaseGames/Data/Skill Editor` | 技能配置 SO(`SKL_*_Data.asset`) | 按 SkillEffectType 分组筛选,右栏含 HitBox 验证 + 资源费预览 | | **Weapon Editor** | `BaseGames/Data/Weapon Editor` | 武器配置 SO(`WPN_*_Data.asset`) | 双面板列表,右栏全属性 + HitBox Prefab 验证 + 快捷操作 | | **Weapon HitBox Wizard** | `BaseGames/Create/Weapon HitBox Prefab` | 武器 HitBox Prefab(4 方向 Ground/Up/Down/Air) | 自动生成 `WPN_{ID}_HitBox.prefab`,支持各方向碰撞体形状配置 | | **Skill HitBox Wizard** | `BaseGames/Create/Skill HitBox Prefab` | 技能 HitBox Prefab(多段伤害支持) | 自动生成 `SKL_{ID}_HitBox.prefab`,可配置 1–4 段 hitBoxCount | | **Input Icon Studio** | `BaseGames/Input Icon Studio` | 按键图标集 SO(`ICN_*.asset`)+ 按键图标 Sprite 映射 | 设备标签栏 + Action 列表覆盖率指示 + 实时编辑 + 交互提示模拟预览 | ### 12.2 场景搭建工具 | 工具名称 | 菜单路径 | 说明 | |---------|---------|------| | **Boot Flow Wizard** | `BaseGames/Scene/Setup/Boot Flow Wizard` | 4 步启动流程一键配置(事件频道 → Persistent 场景 → MainMenu → 验证) | | **Scaffold Persistent Scene** | `BaseGames/Scene/Setup/Scaffold Persistent Scene` | 一键创建 Persistent 场景的 Services/Input/Camera/UI 层次结构 | | **Scaffold Main Menu Scene** | `BaseGames/Scene/Setup/Scaffold Main Menu Scene` | 一键创建 MainMenu 场景基础层次结构 | | **Scaffold Game Room** | `BaseGames/Scene/Setup/Scaffold Game Room` | 一键创建关卡房间场景基础层次结构 | | **Persistent Auto-Loader** | `BaseGames/Scene/Setup/Auto-Open Persistent Scene` | 编辑模式下打开任意场景时自动附加 Persistent(Toggle,仅编辑模式) | | **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 管理工具 | 工具名称 | 菜单路径 | 说明 | |---------|---------|------| | **Rule Sync** | `BaseGames/Addressables/Rule Sync` | 批量扫描/修复分组和标签(基于 `AddressableRules.cs` 规则,支持导出 CSV) | | **Addressable Batch Tool** | `BaseGames/Addressables/Addressable Batch Tool` (Alt+Shift+A) | 三标签操作:① 同步 AddressKeys → ② 文件夹批量注册 → ③ Selection 注册 | | **Asset Reference Graph** | `BaseGames/Addressables/Asset Reference Graph` | 可视化 Addressable 地址间的引用依赖关系 | | **Validate Address Keys** | `BaseGames/Addressables/Validate Address Keys` | 验证 `AddressKeys.cs` 所有常量在 Addressables 中均已注册,构建前自动触发 | ### 12.4 事件系统工具 | 工具名称 | 菜单路径 | 说明 | |---------|---------|------| | **Event Bus Monitor** | `BaseGames/Events/Event Bus Monitor` (Ctrl+Shift+E) | 运行时事件派发监控(类型/侦听器数/触发次数实时显示) | | **Event Chain Viewer** | `BaseGames/Events/Event Chain Viewer` | 叙事事件链可视化,运行时显示完成/满足/等待状态 | | **Create Event Channels** | `BaseGames/Events/Create Event Channels` | 一键生成全局事件频道 SO(幂等,跳过已存在资产) | | **Reimport Event Channels** | `BaseGames/Events/Reimport Event Channels` | 重新导入/刷新全局事件频道 SO | ### 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 工具误报分组或标签不一致。