# 小怪与 Boss Unity 配置手册 > 文件位置:`Docs/Guides/02_Enemy_Boss_Setup_Guide.md` > 版本:1.0 · 适用对象:**策划 / 技术美术** > 对应实现计划:`Docs/Plan/小怪与Boss实现计划-01.md` 本文档面向在 Unity Editor 中负责创建 Prefab、配置 ScriptableObject、制作动画 Clip、搭建行为树的策划开发者。**所有 C# 脚本均已由程序完成**,本文档只涉及 Editor 操作。 --- ## 目录 1. [必读:核心规则(违反会导致运行错误)](#1-必读核心规则) 2. [前置任务:全局配置](#2-前置任务全局配置) 3. [通用操作流程](#3-通用操作流程) 4. [E001 草蛭](#4-e001-草蛭) 5. [E002 簧蛭](#5-e002-簧蛭) 6. [E003 幼蛭](#6-e003-幼蛭) 7. [E004 蛭母(小Boss)](#7-e004-蛭母小boss) 8. [E005 肥蛭(精英怪)](#8-e005-肥蛭精英怪) 9. [E006 讙](#9-e006-讙) 10. [Boss 嘲风](#10-boss-嘲风) 11. [Addressables 注册步骤](#11-addressables-注册步骤) 12. [常见错误排查](#12-常见错误排查) --- ## 1. 必读:核心规则 > ⚠️ 在动手之前请完整阅读本节。以下规则违反后**不会有编译错误**,但运行时动画/AI 会失效。 ### 规则 A:动画永远属于能力脚本,不属于行为树 | 正确做法 | 错误做法 | |---------|---------| | 技能动画在对应 Ability 组件的字段上绑定 ClipTransition | 在行为树中使用 `BD_PlayAnimation` 节点播放技能动画 | | 框架状态动画(Idle/Walk/Run/Dead)在 `EnemyAnimationConfigSO` 绑定 | 在行为树中手动切换 Idle、Walk、Run | **框架自动负责的动画**(不需要任何操作): | 动画 | 自动触发条件 | |------|------------| | Idle | `EnemyBase` 初始化时;`BD_SetAiPhase(Idle)` 时 | | Walk | `BD_SetAiPhase(Patrol)` 时 | | Run | `BD_SetAiPhase(Chase)` 时;`BD_ChasePlayer` 时 | | Dead | HP 归零后 `Die()` 自动触发 | **结论**:行为树只做**条件判断**(`BD_IsXxx`)和**行为触发**(`BD_UseAbility`、`BD_SetAiPhase`、`BD_MoveToPlayer`)。 --- ### 规则 B:能力组件必须挂在 Prefab 子节点 `Abilities/` 下 `EnemyAbilityRegistry` 在游戏开始时自动扫描根节点的所有子 GameObject,收集所有 `EnemyAbilityBase` 子类组件。 **能力组件挂在根节点本身无法被注册**,必须放在子层级(推荐统一放 `Abilities/` 子节点)。 --- ### 规则 C:abilityId 全局唯一 每个 `EnemyAbilitySO` 的 `abilityId` 字段在整个项目中不能重复。推荐命名格式: `{敌人ID}_{技能描述}` — 例:`e001_activate`、`e004_headslam`、`e006_leap` --- ### 规则 D:命名规范(必须严格遵守) | 资产类型 | 命名格式 | 示例 | |---------|---------|------| | 敌人 StatsSO | `ENM_{EnemyID}_Stats.asset` | `ENM_E001_Stats.asset` | | 能力 AbilitySO | `ABL_{EnemyID}_{Name}.asset` | `ABL_E001_Activate.asset` | | 敌人 Prefab | `ENM_{Name}.prefab` | `ENM_CaoZhi.prefab` | | 弹体 Prefab | `PROJ_{Name}.prefab` | `PROJ_Boomerang.prefab` | | 动画 Clip | `{Action}.anim`(无前缀) | `Idle.anim`、`Skill_Start.anim` | | 精灵图 | `{ID}_{Name}_{Action}.png` | `E001_CaoZhi_Idle.png` | --- ## 2. 前置任务:全局配置 在创建任何敌人之前,确认以下全局设置已完成。 ### 2-A:Layer 确认 打开 `Edit → Project Settings → Tags and Layers`,确认以下 Layer 存在: | Layer 名 | 用途 | |---------|------| | `EnemyHitBox` | 敌人攻击碰撞盒(HitBox 组件) | | `EnemyHurtBox` | 敌人受击碰撞盒(HurtBox 组件) | | `EnemyProjectile` | 敌人弹体 | | `PlayerHitBox` | 玩家攻击碰撞盒 | ### 2-B:对象池 PoolKey 注册 以下弹体/小怪 Prefab 需要注册到对象池(在对象池管理 SO 中添加条目)。Pool Key **必须与 Addressable Address 完全一致**: | Pool Key | Prefab | 说明 | |---------|--------|------| | `ENM_YouZhi` | `ENM_YouZhi.prefab` | E005 死亡时生成 E003 | | `PROJ_ZhiMu_Acid` | `PROJ_ZhiMu_Acid.prefab` | E004 酸液弹 | | `PROJ_FeiZhi_Acid` | `PROJ_FeiZhi_Acid.prefab` | E005 酸液弹 | | `PROJ_Boomerang` | `PROJ_Boomerang.prefab` | 嘲风回旋扇 | | `PROJ_TornadoSmall` | `PROJ_TornadoSmall.prefab` | 嘲风小龙卷 | | `PROJ_TornadoLarge` | `PROJ_TornadoLarge.prefab` | 嘲风大龙卷 | | `PROJ_WindStone` | `PROJ_WindStone.prefab` | 嘲风风石 | --- ## 3. 通用操作流程 每个敌人的创建流程分为以下 5 步,后续章节按此模板展开: ``` Step 1 制作动画 Clip Step 2 创建 ScriptableObject(StatsSO + AbilitySO) Step 3 搭建 Prefab 结构并配置组件 Step 4 搭建行为树 Step 5 注册 Addressables ``` ### 如何创建 EnemyStatsSO 右键 `Assets/_Game/Data/Enemies/{EnemyID}/` → **Create → BaseGames/Enemies/Enemy Stats** → 命名 `ENM_{EnemyID}_Stats.asset` ### 如何创建 EnemyAbilitySO 右键 `Assets/_Game/Data/Enemies/{EnemyID}/` → **Create → BaseGames/Enemies/Enemy Ability** → 命名 `ABL_{EnemyID}_{Name}.asset` ### EnemyAnimationConfigSO 标准字段映射 | AnimConfig 字段 | 绑定的 Clip | 框架触发时机 | |----------------|-----------|-----------| | `Idle` | 待机/伪装 Clip | 游戏开始时;`SetAiPhase(Idle)` | | `Walk` | 巡逻移动 Clip | `SetAiPhase(Patrol)` | | `Run` | 追击/快速移动 Clip | `SetAiPhase(Chase)` | | `Turn` | 转身 Clip | `EnemyMovement` 检测到方向变化(需开启 `_enableTurnAnimation`) | | `Dead` | 死亡 Clip | `Die()` | | `Hurt` | 受击 Clip | 框架受击状态 | | `Stagger` | 硬直 Clip | 框架硬直状态 | > ⚠️ 技能动画(如 `Skill_Start`、`Skill_Loop`)**不放在 AnimConfig**,而是直接绑定到各 Ability 组件的 `ClipTransition` 字段。 --- ## 4. E001 草蛭 **设计要点**:默认伪装为环境装饰,感知玩家后激活,进入 Skill_Start→Skill_Loop 追击模式。 ### Step 1:制作动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E001/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Idle.anim` | 伪装待机(循环) | AnimConfig.Idle | | `Move.anim` | 巡逻爬行(循环) | AnimConfig.Walk | | `Flip.anim` | 转身(单次) | AnimConfig.Turn | | `Skill_Start.anim` | 激活前摇(单次) | `PlayClipAbility._clip` | | `Skill_Loop.anim` | 追击循环(循环) | `ContactChaseAbility._loopClip` | | `Skill_End.anim` | 追击收招(单次) | `ContactChaseAbility._endClip` | | `Death.anim` | 死亡(单次) | AnimConfig.Dead | ### Step 2:创建 ScriptableObject **文件路径**:`Assets/_Game/Data/Enemies/E001/` **`ENM_E001_Stats.asset`**(EnemyStatsSO): | 字段 | 说明 | |-----|------| | MaxHP | 策划填写 | | WalkSpeed | 巡逻速度 | | RunSpeed | 追击速度 | | DetectRange | 感知范围(与 aggro 传感器半径一致) | **`ABL_E001_Activate.asset`**(EnemyAbilitySO): | 字段 | 值 | |-----|---| | abilityId | `"e001_activate"` | | cooldown | `0` | | interruptOnHurt | `true` | **`ABL_E001_Chase.asset`**(EnemyAbilitySO): | 字段 | 值 | |-----|---| | abilityId | `"e001_chase"` | | cooldown | `0` | | preferredMaxRange | 与 aggro 传感器半径一致 | ### Step 3:搭建 Prefab **路径**:`Assets/_Game/Prefabs/Enemies/E001/ENM_CaoZhi.prefab` **Prefab 层级结构**: ``` ENM_CaoZhi (根节点) ├── 组件:EnemyBase、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:EnemySensorHub ├── 组件:Rigidbody2D(Dynamic)、Collider2D(主碰撞体) ├── HurtBox/ │ ├── 组件:HurtBox、Collider2D(Is Trigger=true, Layer=EnemyHurtBox) ├── ContactDamageZone/ │ ├── 组件:BodyContactDamage、HitBox、Collider2D(Is Trigger=true, Layer=EnemyHitBox) └── Abilities/ ├── 子节点 Activate_Ability → 组件:PlayClipAbility └── 子节点 Chase_Ability → 组件:ContactChaseAbility ``` **组件配置详情**: **EnemyBase**: - `_stats`:拖入 `ENM_E001_Stats.asset` - `_animConfig`:拖入对应 `EnemyAnimationConfigSO`(需先创建,绑定 Idle/Walk/Run/Turn/Dead Clip) **EnemyMovement**: - `_enableTurnAnimation`:勾选 ✓(使用 Flip 转身动画) **EnemySensorHub**(在 Inspector 中添加 `_slots`): | slotName | Sensor 类型 | 说明 | |---------|-----------|------| | `aggro` | RangeSensor2D | 感知半径 = DetectRange | | `wall_ahead` | RaySensor2D | 向前射线,检测墙壁 | | `ledge` | RaySensor2D | 向前下方射线,检测悬崖 | **PlayClipAbility**(挂在 `Activate_Ability` 子节点): - `_config`:拖入 `ABL_E001_Activate.asset` - `_clip`:拖入 `Skill_Start.anim` 对应的 ClipTransition **ContactChaseAbility**(挂在 `Chase_Ability` 子节点): - `_config`:拖入 `ABL_E001_Chase.asset` - `_loopClip`:`Skill_Loop.anim` - `_endClip`:`Skill_End.anim` - `_contactDamage`:拖入 `ContactDamageZone/` 节点上的 `BodyContactDamage` 组件 - `_sensorHub`:拖入根节点上的 `EnemySensorHub` 组件 - `_aggroSlotName`:`"aggro"` ### Step 4:搭建行为树 在根节点挂载 `BehaviorTree` 组件,创建如下结构: ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → State: Dead │ └── BD_StopMovement │ ├── Sequence [激活] │ ├── Selector │ │ ├── BD_IsAiPhase → Phase: Idle │ │ └── BD_IsAiPhase → Phase: Patrol │ ├── BD_IsSensorDetecting → SlotName: "aggro" │ ├── BD_UseAbility → AbilitySO: ABL_E001_Activate │ └── BD_SetAiPhase → Phase: Chase │ ├── Sequence [追击] │ ├── BD_IsAiPhase → Phase: Chase │ └── BD_UseAbility → AbilitySO: ABL_E001_Chase │ └── Selector [巡逻] ├── Sequence [待机] │ ├── BD_IsAiPhase → Phase: Idle │ └── BD_WaitRandom → Min/Max: 填写待机时长范围 └── Sequence [移动] ├── BD_IsAiPhase → Phase: Patrol └── BD_Patrol ``` > ⚠️ 最外层巡逻节点必须是 **Selector** 而不是 Sequence。否则待机结束后不会进入巡逻分支。 ### Step 5:注册 Addressables - Address:`ENM_CaoZhi` - Group:`Enemies` - Labels:`Enemy` --- ## 5. E002 簧蛭 **设计要点**:固定位置(悬挂天花板),无移动能力。Skill_Loop 期间为脆弱窗口(HurtBox 开启)。 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E002/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Idle.anim` | 待机(循环) | AnimConfig.Idle | | `Skill_Strike.anim` | 出击(单次) | `CeilingHangStrikeAbility._strikeClip` | | `Skill_Loop.anim` | 脆弱悬挂(循环) | `CeilingHangStrikeAbility._loopClip` | | `Skill_End.anim` | 收回(单次) | `CeilingHangStrikeAbility._endClip` | | `Death.anim` | 死亡 | AnimConfig.Dead | ### Step 2:ScriptableObject 路径:`Assets/_Game/Data/Enemies/E002/` **`ENM_E002_Stats.asset`**:WalkSpeed/RunSpeed=0(固定单位)。 **`ABL_E002_CeilingStrike.asset`**: | 字段 | 值 | |-----|---| | abilityId | `"e002_ceiling_strike"` | | cooldown | 悬挂时长+恢复时长(策划填写) | | interruptOnHurt | `false`(技能期间霸体) | 在 `attackSequence` 数组添加一个条目: - `clip`:`Skill_Strike.anim` - `damageSource`:拖入对应的 `DamageSourceSO`(定义伤害量/类型) ### Step 3:搭建 Prefab 路径:`Assets/_Game/Prefabs/Enemies/E002/ENM_HuangZhi.prefab` ``` ENM_HuangZhi (根节点) ├── 组件:EnemyBase ← 注意:不挂 EnemyMovement、NavAgent ├── 组件:EnemySensorHub ├── 组件:Rigidbody2D(Kinematic,Gravity Scale=0) ├── HurtBox/ │ ├── 组件:HurtBox(初始 enabled=false)、Collider2D └── Abilities/ └── 子节点 CeilingStrike_Ability → 组件:CeilingHangStrikeAbility ``` > ⚠️ E002 **不挂** `EnemyMovement`、`EnemyNavAgent`、`NavAgent`、`TransformBasedMovement`,因为它是固定单位。 **CeilingHangStrikeAbility 配置**: - `_config`:`ABL_E002_CeilingStrike.asset` - `_strikeClip`:`Skill_Strike.anim` - `_loopClip`:`Skill_Loop.anim` - `_endClip`:`Skill_End.anim` - `_attackHitBox`:拖入 `AttackHitBox/` 子节点的 HitBox 组件 - `_hurtBox`:拖入 `HurtBox/` 子节点的 HurtBox 组件 - `_hangDuration`:脆弱悬挂时长(秒,策划填写) **EnemySensorHub**: | slotName | Sensor 类型 | 说明 | |---------|-----------|------| | `attack_range` | RangeSensor2D | 正下方矩形区域,检测玩家是否在正下方 | ### Step 4:行为树 ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → Dead │ └── BD_Wait → Duration: 999 │ └── Sequence [攻击] ├── BD_IsSensorDetecting → SlotName: "attack_range" ├── BD_CanUseAbility → AbilitySO: ABL_E002_CeilingStrike └── BD_UseAbility → AbilitySO: ABL_E002_CeilingStrike ``` ### Step 5:Addressables - Address:`ENM_HuangZhi` · Group:`Enemies` · Labels:`Enemy` --- ## 6. E003 幼蛭 **设计要点**:HP=1(一击即死)。支持两种生成路径: ① 场景预置(悬挂天花板,触发器激活) ② E005 肥蛭死亡时从代码生成。 生成后从天花板落下(Kinematic → Dynamic),落地后开始地面追击。 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E003/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Idle.anim` | 天花板吸附待机(循环) | AnimConfig.Idle | | `Fall.anim` | 下落旋转(循环,直到落地) | `AnimatedCeilingDropAbility._fallLoopClip` | | `Move.anim` | 地面移动(循环) | AnimConfig.Walk | | `Skill.anim` | 追击加速(循环) | AnimConfig.Run | | `Death.anim` | 死亡 | AnimConfig.Dead | ### Step 2:ScriptableObject 路径:`Assets/_Game/Data/Enemies/E003/` **`ENM_E003_Stats.asset`**:MaxHP=**1**(一击即死) **`ABL_E003_Fall.asset`**: | 字段 | 值 | |-----|---| | abilityId | `"e003_fall"` | | cooldown | `0` | ### Step 3:Prefab 路径:`Assets/_Game/Prefabs/Enemies/E003/ENM_YouZhi.prefab` ``` ENM_YouZhi (根节点) ├── 组件:E003_YouZhi(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:EnemySensorHub ├── 组件:Rigidbody2D(初始 Body Type=Kinematic,下落能力会自动切换为 Dynamic) ├── HurtBox/ ├── ContactDamageZone/ │ └── 组件:BodyContactDamage(初始 enabled=false,落地后由能力自动启用) └── Abilities/ └── 子节点 Fall_Ability → 组件:AnimatedCeilingDropAbility ``` **AnimatedCeilingDropAbility 配置**: | 字段 | 值 | |-----|---| | `_config` | `ABL_E003_Fall.asset` | | `_fallLoopClip` | `Fall.anim` | | `_fallGravityScale` | `3.5`(策划可调) | | `_maxFallTime` | `3`(超时保护) | | `_groundMask` | 选择 `Ground` Layer | | `_recoveryTime` | `0.1`(落地后短暂停顿) | | `_contactDamage` | 拖入 `ContactDamageZone/` 的 BodyContactDamage | **E003_YouZhi 组件配置**: - `_activateOnSpawn`:勾选 ✓(对象池生成时自动触发下落;若是场景预置则由触发器调用 `ActivateFromCeiling()` 方法) **EnemySensorHub**: | slotName | 类型 | |---------|------| | `aggro` | RangeSensor2D | ### Step 4:行为树 ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → Dead │ └── BD_StopMovement │ ├── Sequence [下落(Idle 阶段,一次性)] │ ├── BD_IsAiPhase → Idle │ └── BD_UseAbility → ABL_E003_Fall ← 落地后能力内部自动 SetAiPhase(Patrol) │ ├── Sequence [感知追击] │ ├── BD_IsSensorDetecting → "aggro" │ └── BD_ChasePlayer ← 自动 SetAiPhase(Chase)+播 AnimConfig.Run │ └── BD_Patrol ← 兜底巡逻,自动 SetAiPhase(Patrol)+播 AnimConfig.Walk ``` ### Step 5:Addressables - Address:`ENM_YouZhi` · Group:`Enemies` · Labels:`Enemy`, `Poolable`, `Preload` > ⚠️ E003 必须标记 `Poolable` 和 `Preload`,因为 E005 死亡时会从对象池动态生成它。 --- ## 7. E004 蛭母(小Boss) **设计要点**:拥有出场演出、三种战斗技能(撕咬/头槌/酸液)、翻身能力(玩家绕后时触发),死亡分两阶段(Death_Pre 无敌演出 → 真正死亡)。 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E004/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Static.anim` | 休眠待机(1帧循环) | AnimConfig.Idle | | `Move.anim` | 战斗移动(循环) | AnimConfig.Walk | | `Appear.anim` | 出场嚎叫(单次) | `AppearAbility._appearClip` | | `Skill01.anim` | 撕咬(单次) | `MeleeAttackAbility.attackSequence[0].clip` | | `Skill02_Start.anim` | 头槌起手(单次) | `RepeatSlamAbility._startClip` | | `Skill02_Loop.anim` | 头槌砸地(单次,循环N次) | `RepeatSlamAbility._loopClip` | | `Skill02_End.anim` | 头槌收招(单次) | `RepeatSlamAbility._endClip` | | `Skill03.anim` | 吐酸液(单次) | `ProjectileAttackAbility.attackSequence[0/1].clip` | | `Flip.anim` | 翻身转向(单次) | `FacePlayerAbility._faceClip` | | `Death_Pre.anim` | 死亡前摇(循环,约3秒) | `E004_ZhiMu._deathPreClip` | | `Death.anim` | 死亡消散(单次) | AnimConfig.Dead | ### Step 2:ScriptableObject 路径:`Assets/_Game/Data/Enemies/E004/` | 文件名 | abilityId | 关键配置 | |-------|-----------|---------| | `ENM_E004_Stats.asset` | — | HP/速度/感知范围 | | `ABL_E004_Appear.asset` | `"e004_appear"` | cooldown=0 | | `ABL_E004_Bite.asset` | `"e004_bite"` | preferredMaxRange=近战半径;attackSequence[0] 绑定 DamageSourceSO | | `ABL_E004_HeadSlam.asset` | `"e004_headslam"` | preferredMaxRange=中距半径;interruptOnHurt=false(霸体) | | `ABL_E004_Acid.asset` | `"e004_acid"` | preferredMinRange=2 | | `ABL_E004_Flip.asset` | `"e004_flip"` | cooldown=0.3 | ### Step 3:Prefab 路径:`Assets/_Game/Prefabs/Enemies/E004/ENM_ZhiMu.prefab` ``` ENM_ZhiMu (根节点) ├── 组件:E004_ZhiMu(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:EnemySensorHub ├── 组件:EnemyFeedback、Rigidbody2D ├── HurtBox/ → 组件:HurtBox、Collider2D ├── BiteHitBox/ → 组件:HitBox、Collider2D(撕咬用) ├── SlamHitBox/ → 组件:HitBox、Collider2D(头槌用) ├── AcidMuzzle/ → 空 Transform(酸液发射点) └── Abilities/ ├── Appear_Ability → 组件:AppearAbility ├── Bite_Ability → 组件:MeleeAttackAbility ├── HeadSlam_Ability → 组件:RepeatSlamAbility ├── Acid_Ability → 组件:ProjectileAttackAbility └── Flip_Ability → 组件:FacePlayerAbility ``` **E004_ZhiMu 组件配置**: - `_deathPreClip`:拖入 `Death_Pre.anim` - `_hurtBox`:拖入 `HurtBox/` 组件 - `_deathPreDuration`:`3`(与 Death_Pre 动画时长一致,策划调整) **AppearAbility**: - `_config`:`ABL_E004_Appear.asset` - `_appearClip`:`Appear.anim` **MeleeAttackAbility**(撕咬): - `_config`:`ABL_E004_Bite.asset` - 在 ABL_E004_Bite 的 `attackSequence[0]` 中: - `clip`:`Skill01.anim` - `hitBoxSlot`:`"bite"`(与 `_hitBoxSlots` 中的 slotName 对应) - `hitBoxEnterT`:`0.30`(Clip 时长的 30% 时激活 HitBox) - `hitBoxExitT`:`0.60`(Clip 时长的 60% 时停用 HitBox) - 在 MeleeAttackAbility 的 `_hitBoxSlots` 中添加:slotName=`"bite"`, hitBox=拖入 `BiteHitBox/` **RepeatSlamAbility**(头槌): - `_config`:`ABL_E004_HeadSlam.asset` - `_startClip`:`Skill02_Start.anim` - `_loopClip`:`Skill02_Loop.anim` - `_endClip`:`Skill02_End.anim` - `_hitBox`:拖入 `SlamHitBox/` - `_slamCount`:`2`(策划调整) - `_hitActiveTime`:`0.15` - `_staggerDuration`:`1.2`(收招后硬直,供玩家反击) **ProjectileAttackAbility**(酸液): - `_config`:`ABL_E004_Acid.asset` - `_muzzle`:拖入 `AcidMuzzle/` Transform - ABL_E004_Acid 的 `attackSequence[0]`: - `clip`:`Skill03.anim` - `projectileCount`:`3`(同时发射数量) - `spreadAngleDeg`:`30`(扩散角) - `projectileFireT`:`0.5`(Clip 的 50% 时发射) - `projectileConfig`:指向 `PROJ_ZhiMu_Acid` 的弹体配置 SO **FacePlayerAbility**(翻身): - `_config`:`ABL_E004_Flip.asset` - `_faceClip`:`Flip.anim` **EnemySensorHub**: | slotName | 类型 | |---------|------| | `aggro` | RangeSensor2D | | `los` | LOSSensor2D | ### Step 4:行为树 ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → Dead │ └── BD_StopMovement │ ├── Sequence [出场(仅首次,Idle阶段)] │ ├── BD_IsAiPhase → Idle │ └── BD_UseAbility → ABL_E004_Appear ← 内部自动 SetAiPhase(Combat) │ └── Sequence [战斗] ├── BD_IsAiPhase → Combat └── Selector ├── Sequence [翻身(技能间隙+玩家在背后)] │ ├── BD_CanUseAbility → ABL_E004_Flip ← CanUse 内部已检测无技能运行且玩家在背后 │ └── BD_UseAbility → ABL_E004_Flip │ ├── Sequence [撕咬(近距)] │ ├── BD_CanUseAbility → ABL_E004_Bite, CheckRange=true │ └── BD_UseAbility → ABL_E004_Bite │ ├── Sequence [头槌(中距)] │ ├── BD_CanUseAbility → ABL_E004_HeadSlam, CheckRange=true │ └── BD_UseAbility → ABL_E004_HeadSlam │ ├── Sequence [酸液(远程)] │ ├── BD_CanUseAbility → ABL_E004_Acid │ └── BD_UseAbility → ABL_E004_Acid │ └── BD_MoveToPlayer ``` > ⚠️ `BD_CanUseAbility(ABL_E004_Flip)` 无需额外检测"无其他技能运行",该逻辑已内置在 `FacePlayerAbility.CanUse` 中。 ### Step 5:Addressables - Address:`ENM_ZhiMu` · Group:`Enemies` · Labels:`Enemy` --- ## 8. E005 肥蛭(精英怪) **设计要点**:撕咬技能有后摇脆弱窗口(HurtBox 激活),死亡时 Death_Pre 动画中通过 AnimationEvent 生成多只 E003。 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E005/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Idle.anim` | 待机(循环) | AnimConfig.Idle | | `Move.anim` | 移动(循环) | AnimConfig.Walk/Run | | `Skill01.anim` | 撕咬(单次) | `MeleeVulnerabilityAbility._attackClip` | | `Skill02.anim` | 吐酸液(单次,连续两轮复用) | `ProjectileAttackAbility.attackSequence[0/1].clip` | | `Death_Pre.anim` | 死亡前摇(含 AnimationEvent) | `E005_FeiZhi._deathPreClip` | | `Death.anim` | 死亡 | AnimConfig.Dead | > ⚠️ **Death_Pre AnimationEvent 设置(关键步骤)**: > 1. 在 Unity 动画编辑器中打开 `Death_Pre.anim` > 2. 在适当帧(E003 应该出现的时刻)添加 AnimationEvent > 3. 函数名:`SpawnProjectile`,字符串参数:`"spawn_e003"` ### Step 2:ScriptableObject 路径:`Assets/_Game/Data/Enemies/E005/` | 文件名 | abilityId | 配置 | |-------|-----------|------| | `ENM_E005_Stats.asset` | — | HP/速度 | | `ABL_E005_Bite.asset` | `"e005_bite"` | preferredMaxRange=近战半径 | | `ABL_E005_Acid.asset` | `"e005_acid"` | 无范围限制 | ### Step 3:Prefab 路径:`Assets/_Game/Prefabs/Enemies/E005/ENM_FeiZhi.prefab` ``` ENM_FeiZhi (根节点) ├── 组件:E005_FeiZhi(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:EnemySensorHub ├── 组件:Rigidbody2D ├── HurtBox/ → 组件:HurtBox ├── BiteHitBox/ → 组件:HitBox ├── AcidMuzzle/ → 空 Transform └── Abilities/ ├── Bite_Ability → 组件:MeleeVulnerabilityAbility └── Acid_Ability → 组件:ProjectileAttackAbility ``` **E005_FeiZhi 配置**: - `_deathPreClip`:`Death_Pre.anim` - `_hurtBox`:`HurtBox/` 组件 - `_deathPreDuration`:与动画时长一致 - `_spawnCount`:`3`(生成 E003 数量,策划调整) - `_spawnRadius`:`1.5`(生成散布半径) **MeleeVulnerabilityAbility(撕咬)**: - `_config`:`ABL_E005_Bite.asset` - `_attackClip`:`Skill01.anim` - `_hitBox`:`BiteHitBox/` - `_hurtBox`:`HurtBox/`(后摇期间开放脆弱窗口) - `_hitEnterT`:`0.30`(攻击 30% 时激活 HitBox) - `_hitExitT`:`0.60`(攻击 60% 时停用 HitBox) - `_staggerDuration`:`1.0`(后摇脆弱窗口时长,策划调整) **ProjectileAttackAbility(酸液,连续两次)**: - `_config`:`ABL_E005_Acid.asset` - `_muzzle`:`AcidMuzzle/` - ABL_E005_Acid 的 `attackSequence`(需要 **2 个条目**): - `[0]`:clip=`Skill02.anim`, projectileCount=1, projectileFireT=0.6, postDelay=0.2 - `[1]`:clip=`Skill02.anim`, projectileCount=1, projectileFireT=0.6 > ⚠️ 设计要求"连续两次吐出"必须用 **2个 attackSequence 条目**,每条发射1颗。如果用 projectileCount=2 会同帧射出 2 颗,不是连续动作。 ### Step 4:行为树 ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → Dead │ └── BD_StopMovement │ ├── Sequence [撕咬(近距)] │ ├── BD_CanUseAbility → ABL_E005_Bite, CheckRange=true │ └── BD_UseAbility → ABL_E005_Bite │ ├── Sequence [酸液(远程)] │ ├── BD_CanUseAbility → ABL_E005_Acid │ └── BD_UseAbility → ABL_E005_Acid │ └── BD_ChasePlayer ← 自动 SetAiPhase(Chase)+播 AnimConfig.Run ``` ### Step 5:Addressables - Address:`ENM_FeiZhi` · Group:`Enemies` · Labels:`Enemy` --- ## 9. E006 讙 **设计要点**:跳跃攻击(动画原地,Rigidbody2D 冲量负责实际位移)。Flip 由巡逻转身自动处理,无需专用 Ability。 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/E006/Animations/` | Clip 文件名 | 用途 | 绑定位置 | |-----------|------|---------| | `Idle.anim` | 待机 | AnimConfig.Idle | | `Move.anim` | 巡逻移动 | AnimConfig.Walk | | `Flip.anim` | 转身 | AnimConfig.Turn | | `Skill.anim` | 跳跃攻击(含起跳/飞行/落地姿态) | `LeapAttackAbility`(attackSequence[0].clip) | | `Death.anim` | 死亡 | AnimConfig.Dead | ### Step 2:ScriptableObject 路径:`Assets/_Game/Data/Enemies/E006/` **`ABL_E006_Leap.asset`**: | 字段 | 值 | |-----|---| | abilityId | `"e006_leap"` | | cooldown | 攻击间隔(策划填写) | | attackSequence[0].clip | `Skill.anim` | ### Step 3:Prefab 路径:`Assets/_Game/Prefabs/Enemies/E006/ENM_Huan.prefab` ``` ENM_Huan (根节点) ├── 组件:EnemyBase、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:EnemySensorHub ├── 组件:Rigidbody2D(Dynamic) ├── HurtBox/ ├── LandingHitBox/ → 组件:HitBox(落地时的攻击判定) └── Abilities/ └── Leap_Ability → 组件:LeapAttackAbility ``` **EnemyMovement**: - `_enableTurnAnimation`:勾选 ✓ **LeapAttackAbility 配置**: - `_config`:`ABL_E006_Leap.asset` - `_jumpHeight`、`_maxRange`:策划填写 - `_windupTime`:起跳前摇时间(秒) - `_recoveryTime`:落地硬直时间 - `_groundMask`:Ground Layer - `_landingHitBox`:拖入 `LandingHitBox/` **EnemySensorHub**: | slotName | 类型 | |---------|------| | `aggro` | RangeSensor2D | | `wall_ahead` | RaySensor2D | | `ledge` | RaySensor2D | ### Step 4:行为树 ``` Selector ├── Sequence [死亡] │ ├── BD_IsStateMatch → Dead │ └── BD_StopMovement │ ├── Sequence [跳跃攻击] │ ├── BD_IsSensorDetecting → "aggro" │ ├── BD_CanUseAbility → ABL_E006_Leap │ └── BD_UseAbility → ABL_E006_Leap │ └── BD_Patrol ← wall_ahead + ledge 槽驱动翻转(含 Turn 动画) ``` ### Step 5:Addressables - Address:`ENM_Huan` · Group:`Enemies` · Labels:`Enemy` --- ## 10. Boss 嘲风 **设计要点**: - **Phase 0(地面)**:4 技能加权随机(回旋扇/扇形连击/小龙卷/大龙卷) - **Phase 1(空中)**:HP 低于 50% 触发过渡,进入悬浮阶段,使用风石技能 + 击落机制 - **击落机制**:Phase 1 被命中 N 次后触发击落序列(落地硬直→恢复浮空) - **击败演出**:完整的 4 段过场动画序列 ### Step 1:动画 Clip 路径:`Assets/_Game/Art/Characters/Enemies/ChaoFeng/Animations/` **状态动画**(绑定 AnimConfig): | Clip 文件名 | AnimConfig 字段 | |-----------|----------------| | `Idle.anim` | Idle | | `Move.anim` | Walk | | `Dead.anim` | Dead | **技能动画**(绑定 BossSkillSO.skillAnimation): | Clip 文件名 | 对应技能 | |-----------|--------| | `Boomerang.anim` | 回旋扇主动画 | | `Boomerang_End.anim` | 回旋扇收招(绑定 `ChaoFengBoss._boomerangEndClip`) | | `FanCombo_01.anim`~`FanCombo_03.anim` | 扇形三连击各段 | | `TornadoSmall.anim` | 小龙卷 | | `TornadoLarge.anim` | 大龙卷 | | `WindStone.anim` | 风石(Phase 2 专属) | **过渡/演出动画**(绑定 ChaoFengBoss 字段): | Clip 文件名 | 绑定字段 | |-----------|--------| | `PhaseTransition.anim` | `_phaseTransitionClip`(上浮过渡动画) | | `KnockdownHit.anim` | `ChaoFengKnockdownCounter._knockdownHitClip`(被打落时) | | `Stagger.anim` | `ChaoFengKnockdownCounter._staggerClip`(落地硬直,复用为 Defeat_Pant) | | `Defeat_Struggle.anim` | `_defeatStruggleClip`(击败时空中挣扎) | | `Defeat_Pant.anim` | `_defeatPantClip`(倒地喘气) | | `Defeat_StandUp.anim` | `_defeatStandUpClip`(站起) | ### Step 2:ScriptableObject(BossSkillSO) 路径:`Assets/_Game/Data/Enemies/ChaoFeng/` > ⚠️ 嘲风使用 **BossSkillSO**(不是 EnemyAbilitySO)。右键 → **Create → BaseGames/Boss/Boss Skill** | 文件名 | skillId | availablePhaseIndices | weight | |-------|---------|----------------------|--------| | `ABL_ChaoFeng_Boomerang.asset` | `"boomerang"` | `[0]` | `1.0` | | `ABL_ChaoFeng_FanCombo.asset` | `"fan_combo"` | `[0]` | `1.5` | | `ABL_ChaoFeng_TornadoSmall.asset` | `"tornado_small"` | `[0]` | `1.2` | | `ABL_ChaoFeng_TornadoLarge.asset` | `"tornado_large"` | `[0]` | `0.8` | | `ABL_ChaoFeng_WindStone.asset` | `"wind_stone"` | `[1]` | Phase 2 专属 | 每个 BossSkillSO 的 `skillAnimation` 字段绑定对应 Clip。 **`ENM_ChaoFeng_Stats.asset`**:HP/速度。 ### Step 3:弹体 Prefab 在制作嘲风 Prefab 之前,需要先创建弹体。 #### PROJ_Boomerang.prefab 路径:`Assets/_Game/Prefabs/Combat/Projectiles/PROJ_Boomerang.prefab` ``` PROJ_Boomerang (根节点) ├── 组件:ReturnProjectile(C# 脚本,继承 Projectile) ├── 组件:Rigidbody2D(Dynamic) ├── 组件:PooledObject(必须,用于对象池回收) └── HitBox/ → 组件:HitBox、Collider2D(Layer=EnemyProjectile) ``` **ReturnProjectile 配置**: - `_maxRange`:最大飞行距离(策划填写) - `_returnSpeed`:返回速度(策划填写) - `_config`:弹体配置 SO(`ProjectileConfigSO`,设置 Speed/Lifetime/DamageSource) > ⚠️ Addressables 配置:Address=`PROJ_Boomerang`, Group=`Projectiles`, Labels=`Poolable`, `Preload` #### 其他弹体 Prefab `PROJ_TornadoSmall`、`PROJ_TornadoLarge`、`PROJ_WindStone`:使用现有 Projectile 脚本,配置方式参考项目中已有的弹体。 ### Step 4:搭建嘲风 Prefab 路径:`Assets/_Game/Prefabs/Enemies/ChaoFeng/ENM_ChaoFeng.prefab` ``` ENM_ChaoFeng (根节点) ├── 组件:ChaoFengBoss(C# 脚本) ├── 组件:EnemyMovement ├── 组件:EnemyNavAgent、NavAgent、TransformBasedMovement ├── 组件:BossSkillExecutor(Boss 技能执行器) ├── 组件:ChaoFengFloatController(浮空控制器) ├── 组件:ChaoFengKnockdownCounter(击落计数器) ├── 组件:EnemyFeedback ├── 组件:Rigidbody2D(Dynamic,击落/落地时由 ChaoFengFloatController 切换为 Kinematic) ├── HurtBox/ → 组件:HurtBox ├── Phase1HitBoxes/ │ ├── FanCombo_HitBox_1/ → HitBox │ ├── FanCombo_HitBox_2/ → HitBox │ ├── FanCombo_HitBox_3/ → HitBox │ └── Tornado_HitBox/ → HitBox ├── Muzzles/ │ ├── BoomerangMuzzle/ → 空 Transform(回旋扇发射点) │ ├── TornadoMuzzle/ → 空 Transform │ └── WindStoneMuzzle/ → 空 Transform └── BehaviorTree [BehaviorDesigner 组件] ``` **ChaoFengBoss 字段配置**: | 字段 | 拖入内容 | |-----|---------| | `_floatController` | 根节点 ChaoFengFloatController 组件 | | `_knockdownCounter` | 根节点 ChaoFengKnockdownCounter 组件 | | `_phaseTransitionClip` | `PhaseTransition.anim` | | `_boomerangEndClip` | `Boomerang_End.anim` | | `_boomerangMuzzle` | `Muzzles/BoomerangMuzzle` Transform | | `_tornadoMuzzle` | `Muzzles/TornadoMuzzle` Transform | | `_windStoneMuzzle` | `Muzzles/WindStoneMuzzle` Transform | | `_defeatStruggleClip` | `Defeat_Struggle.anim` | | `_defeatPantClip` | `Defeat_Pant.anim` | | `_defeatStandUpClip` | `Defeat_StandUp.anim` | | `_defeatPantDuration` | `3`(倒地喘气时长,策划调整) | | `_onDefeatWhiteFlash` | 拖入白屏效果的 UnityEvent 接收者(可接 CameraManager 方法) | **ChaoFengFloatController 配置**: | 字段 | 值 | |-----|---| | `_floatHeight` | 悬空高度(米,策划填写) | | `_riseDuration` | 上浮时长(推荐约 1.5 秒) | | `_fallDuration` | 落下时长(推荐约 0.8 秒) | | `_rb` | 拖入根节点 Rigidbody2D | **ChaoFengKnockdownCounter 配置**: | 字段 | 值 | |-----|---| | `_threshold` | 击落所需命中次数(策划填写,推荐 8) | | `_boss` | 拖入根节点 ChaoFengBoss 组件 | | `_floatCtrl` | 拖入根节点 ChaoFengFloatController 组件 | | `_knockdownHitClip` | `KnockdownHit.anim` | | `_staggerClip` | `Stagger.anim`(与 Defeat_Pant 可共用同一 Clip) | | `_staggerDuration` | `3`(落地硬直时长,策划调整) | **BossBase 相关配置(EnemyBase 父类)**: - `_stats`:`ENM_ChaoFeng_Stats.asset` - 在 `BossSkillExecutor` 组件中,添加所有 5 个 BossSkillSO(Boomerang/FanCombo/TornadoSmall/TornadoLarge/WindStone) ### Step 5:搭建嘲风行为树 > ⚠️ **重要**:嘲风只有**一棵**行为树,不要为 Phase 1 和 Phase 2 创建两棵树。 ``` Selector [嘲风根节点] │ ├── Sequence [Phase 2 (HP < 50%)] │ ├── BD_IsHPBelow → ratio: 0.5 │ ├── BD_BossPhaseTransition → targetPhase: 1, invincibleDuration: 2.0 │ │ (约 1.5s 上浮 + 0.5s 缓冲;过渡中无敌;完成后 CurrentPhase=1) │ └── Selector [Phase 2 战斗] │ ├── BD_UseBossSkillWeighted ← 仅 wind_stone(availablePhaseIndices=[1]) │ └── BD_Wait → Duration: 0.5 │ └── Selector [Phase 1 地面战斗] ← HP > 50% 时走此分支 ├── BD_UseBossSkillWeighted ← 4 个 Phase 0 技能加权随机 └── BD_MoveToPlayer ``` > ⚠️ **关键架构说明**: > - `BD_BossPhaseTransition` 必须位于 Phase 2 Sequence 的**中间**,而非独立的并列节点。 > - 过渡完成后(`CurrentPhase>=1`),`BD_BossPhaseTransition` 每 tick 立即返回 Success,Sequence 继续执行下方的战斗节点。 > - 若两者为并列节点,过渡完成后父 Selector 只要第一个节点成功就停止,永远不会执行战斗节点。 > ⚠️ `BD_BossPhaseTransition.invincibleDuration` 必须 **≥ `_riseDuration` + 缓冲**(推荐 2.0 秒)。 > 上浮动画在无敌期开始时立即播放,确保浮空完成后无敌期才结束。 ### 回旋扇 AnimationEvent 设置 1. 打开 `Boomerang.anim` 2. 在发射时机帧添加 AnimationEvent 3. 函数名:`SpawnProjectile`,字符串参数:`"boomerang"` ### 其他技能 AnimationEvent 设置 | 技能动画 | AnimationEvent 参数 | |--------|-------------------| | 小龙卷 | `SpawnProjectile("tornado_small")` | | 大龙卷 | `SpawnProjectile("tornado_large")` | | 风石 | `SpawnProjectile("wind_stone")` | ### Step 6:Addressables - Address:`ENM_ChaoFeng` · Group:`Boss_ChaoFeng` · Labels:不加 Enemy 标签 --- ## 11. Addressables 注册步骤 1. 打开 `Window → Asset Management → Addressables → Groups` 2. 找到对应 Group(Enemies / Boss_ChaoFeng / Projectiles) 3. 将 Prefab 拖入对应 Group 4. 在 Address 字段填入规范名称(如 `ENM_YouZhi`) 5. 在 Labels 栏勾选对应标签 6. 点击 `Build → New Build → Default Build Script` 更新资产 **Addressables 汇总表**: | Address | Group | Labels | |---------|-------|--------| | `ENM_CaoZhi` | Enemies | Enemy | | `ENM_HuangZhi` | Enemies | Enemy | | `ENM_YouZhi` | Enemies | Enemy, Poolable, Preload | | `ENM_ZhiMu` | Enemies | Enemy | | `ENM_FeiZhi` | Enemies | Enemy | | `ENM_Huan` | Enemies | Enemy | | `ENM_ChaoFeng` | Boss_ChaoFeng | — | | `PROJ_Boomerang` | Projectiles | Poolable, Preload | | `PROJ_ZhiMu_Acid` | Projectiles | Poolable, Preload | | `PROJ_FeiZhi_Acid` | Projectiles | Poolable, Preload | | `PROJ_TornadoSmall` | Projectiles | Poolable, Preload | | `PROJ_TornadoLarge` | Projectiles | Poolable, Preload | | `PROJ_WindStone` | Projectiles | Poolable, Preload | --- ## 12. 常见错误排查 ### ❌ 技能触发后动画不播放 **原因**:能力 SO(EnemyAbilitySO)的 `attackSequence` 中 `clip` 字段未绑定 Clip,或 Ability 组件上的 `ClipTransition` 字段未绑定。 **修复**:检查 Inspector,确认所有 `ClipTransition` 字段已拖入对应 `.anim` 文件。 --- ### ❌ BD_UseAbility 没有效果(技能没有执行) **原因 A**:Ability 组件没有挂在子节点,而是挂在根节点本身。 **修复**:将 Ability 组件移到 `Abilities/` 子节点。 **原因 B**:`abilityId` 与 SO 中的 `abilityId` 不一致(大小写或拼写错误)。 **修复**:对照 SO 的 `abilityId` 字段,确认拼写完全一致。 --- ### ❌ E003 出现后不下落 **原因 A**:`AnimatedCeilingDropAbility._groundMask` 未设置,导致落地检测失败,能力超时后强制结束。 **修复**:将 Ground Layer 加入 `_groundMask`。 **原因 B**:`E003_YouZhi._activateOnSpawn` 未勾选(对象池路径无法触发下落)。 **修复**:在 Inspector 勾选 `_activateOnSpawn`。 --- ### ❌ E005 死亡后没有生成 E003 **原因 A**:`Death_Pre.anim` 中没有 AnimationEvent,或函数名/参数拼写错误。 **修复**:打开动画编辑器,确认 AnimationEvent 的函数为 `SpawnProjectile`,参数为 `"spawn_e003"`(区分大小写)。 **原因 B**:`ENM_YouZhi` 未注册到 Addressables 或 Pool Key 拼写错误。 **修复**:确认 Addressable Address 和对象池 Pool Key 均为 `ENM_YouZhi`(完全一致)。 --- ### ❌ E004 Flip 动画不触发 **原因**:`ABL_E004_Flip` 的条件由 `FacePlayerAbility.CanUse` 内置检测(无其他技能运行 + 玩家在背后),不需要在行为树里额外检测。 **验证**:打开 Runtime 调试,确认 `FacePlayerAbility.CanUse` 返回 true。常见失效原因是另一个技能仍在执行(`IsRunning=true`)。 --- ### ❌ 嘲风 Phase 2 只执行一次过渡,之后不战斗 **原因**:`BD_BossPhaseTransition` 节点被放在独立的并列 Selector 下,而不是内嵌在 Phase 2 Sequence 中间。 **修复**:参照本文档 §10 的行为树结构,确认 `BD_BossPhaseTransition` 是 Phase 2 Sequence 的中间节点,之后跟着战斗 Selector。 --- ### ❌ 嘲风上浮后动画还是地面状态 **原因**:`BD_BossPhaseTransition.invincibleDuration` 设置过短,浮空还没完成无敌期就结束了,后续被 BT 打断。 **修复**:将 `invincibleDuration` 设为 **≥ `_riseDuration` + 0.5 缓冲**(推荐 2.0 秒)。 --- ### ❌ 回旋扇飞出后不回来 **原因 A**:`ReturnProjectile.SetOwner()` 没有被调用,`_ownerTransform` 为 null。 **验证**:确认 `ChaoFengBoss.SpawnProjectile("boomerang")` 中调用了 `go.GetComponent()?.SetOwner(transform)`。这是 C# 代码,程序检查,策划确认 AnimationEvent 的 payload 拼写正确(`"boomerang"` 全小写)。 **原因 B**:`PROJ_Boomerang` 的 Prefab 根节点没有挂 `PooledObject` 组件。 **修复**:添加 `PooledObject` 组件。 --- > 如遇到本文档未涵盖的问题,请联系程序查看 `Docs/Plan/小怪与Boss实现计划-01.md` 中的架构关键约束章节,或查阅 `Docs/Architecture/07_EnemyModule.md`。