Files
zeling_v2/Docs/Guides/02_Enemy_Boss_Setup_Guide.md

40 KiB
Raw Blame History

小怪与 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. 必读:核心规则(违反会导致运行错误)
  2. 前置任务:全局配置
  3. 通用操作流程
  4. E001 草蛭
  5. E002 簧蛭
  6. E003 幼蛭
  7. E004 蛭母小Boss
  8. E005 肥蛭(精英怪)
  9. E006 讙
  10. Boss 嘲风
  11. Addressables 注册步骤
  12. 常见错误排查

1. 必读:核心规则

⚠️ 在动手之前请完整阅读本节。以下规则违反后不会有编译错误,但运行时动画/AI 会失效。

规则 A动画永远属于能力脚本不属于行为树

正确做法 错误做法
技能动画在对应 Ability 组件的字段上绑定 ClipTransition 在行为树中使用 BD_PlayAnimation 节点播放技能动画
框架状态动画Idle/Walk/Run/DeadEnemyAnimationConfigSO 绑定 在行为树中手动切换 Idle、Walk、Run

框架自动负责的动画(不需要任何操作):

动画 自动触发条件
Idle EnemyBase 初始化时;BD_SetAiPhase(Idle)
Walk BD_SetAiPhase(Patrol)
Run BD_SetAiPhase(Chase) 时;BD_ChasePlayer
Dead HP 归零后 Die() 自动触发

结论:行为树只做条件判断BD_IsXxx)和行为触发BD_UseAbilityBD_SetAiPhaseBD_MoveToPlayer)。


规则 B能力组件必须挂在 Prefab 子节点 Abilities/

EnemyAbilityRegistry 在游戏开始时自动扫描根节点的所有子 GameObject收集所有 EnemyAbilityBase 子类组件。
能力组件挂在根节点本身无法被注册,必须放在子层级(推荐统一放 Abilities/ 子节点)。


规则 CabilityId 全局唯一

每个 EnemyAbilitySOabilityId 字段在整个项目中不能重复。推荐命名格式:
{敌人ID}_{技能描述} — 例:e001_activatee004_headslame006_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.animSkill_Start.anim
精灵图 {ID}_{Name}_{Action}.png E001_CaoZhi_Idle.png

2. 前置任务:全局配置

在创建任何敌人之前,确认以下全局设置已完成。

2-ALayer 确认

打开 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  创建 ScriptableObjectStatsSO + 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_StartSkill_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.assetEnemyStatsSO

字段 说明
MaxHP 策划填写
WalkSpeed 巡逻速度
RunSpeed 追击速度
DetectRange 感知范围(与 aggro 传感器半径一致)

ABL_E001_Activate.assetEnemyAbilitySO

字段
abilityId "e001_activate"
cooldown 0
interruptOnHurt true

ABL_E001_Chase.assetEnemyAbilitySO

字段
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
├── 组件Rigidbody2DDynamic、Collider2D主碰撞体
├── HurtBox/
│   ├── 组件HurtBox、Collider2DIs Trigger=true, Layer=EnemyHurtBox
├── ContactDamageZone/
│   ├── 组件BodyContactDamage、HitBox、Collider2DIs 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
  • _loopClipSkill_Loop.anim
  • _endClipSkill_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

  • AddressENM_CaoZhi
  • GroupEnemies
  • LabelsEnemy

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 2ScriptableObject

路径:Assets/_Game/Data/Enemies/E002/

ENM_E002_Stats.assetWalkSpeed/RunSpeed=0固定单位

ABL_E002_CeilingStrike.asset

字段
abilityId "e002_ceiling_strike"
cooldown 悬挂时长+恢复时长(策划填写)
interruptOnHurt false(技能期间霸体)

attackSequence 数组添加一个条目:

  • clipSkill_Strike.anim
  • damageSource:拖入对应的 DamageSourceSO(定义伤害量/类型)

Step 3搭建 Prefab

路径:Assets/_Game/Prefabs/Enemies/E002/ENM_HuangZhi.prefab

ENM_HuangZhi (根节点)
├── 组件EnemyBase  ← 注意:不挂 EnemyMovement、NavAgent
├── 组件EnemySensorHub
├── 组件Rigidbody2DKinematicGravity Scale=0
├── HurtBox/
│   ├── 组件HurtBox初始 enabled=false、Collider2D
└── Abilities/
    └── 子节点 CeilingStrike_Ability → 组件CeilingHangStrikeAbility

⚠️ E002 不挂 EnemyMovementEnemyNavAgentNavAgentTransformBasedMovement,因为它是固定单位。

CeilingHangStrikeAbility 配置

  • _configABL_E002_CeilingStrike.asset
  • _strikeClipSkill_Strike.anim
  • _loopClipSkill_Loop.anim
  • _endClipSkill_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 5Addressables

  • AddressENM_HuangZhi · GroupEnemies · LabelsEnemy

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 2ScriptableObject

路径:Assets/_Game/Data/Enemies/E003/

ENM_E003_Stats.assetMaxHP=1(一击即死)

ABL_E003_Fall.asset

字段
abilityId "e003_fall"
cooldown 0

Step 3Prefab

路径:Assets/_Game/Prefabs/Enemies/E003/ENM_YouZhi.prefab

ENM_YouZhi (根节点)
├── 组件E003_YouZhiC# 脚本、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 5Addressables

  • AddressENM_YouZhi · GroupEnemies · LabelsEnemy, Poolable, Preload

⚠️ E003 必须标记 PoolablePreload,因为 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 2ScriptableObject

路径: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 3Prefab

路径:Assets/_Game/Prefabs/Enemies/E004/ENM_ZhiMu.prefab

ENM_ZhiMu (根节点)
├── 组件E004_ZhiMuC# 脚本、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/ 组件
  • _deathPreDuration3(与 Death_Pre 动画时长一致,策划调整)

AppearAbility

  • _configABL_E004_Appear.asset
  • _appearClipAppear.anim

MeleeAttackAbility(撕咬):

  • _configABL_E004_Bite.asset
  • 在 ABL_E004_Bite 的 attackSequence[0] 中:
    • clipSkill01.anim
    • hitBoxSlot"bite"(与 _hitBoxSlots 中的 slotName 对应)
    • hitBoxEnterT0.30Clip 时长的 30% 时激活 HitBox
    • hitBoxExitT0.60Clip 时长的 60% 时停用 HitBox
  • 在 MeleeAttackAbility 的 _hitBoxSlots 中添加slotName="bite", hitBox=拖入 BiteHitBox/

RepeatSlamAbility(头槌):

  • _configABL_E004_HeadSlam.asset
  • _startClipSkill02_Start.anim
  • _loopClipSkill02_Loop.anim
  • _endClipSkill02_End.anim
  • _hitBox:拖入 SlamHitBox/
  • _slamCount2(策划调整)
  • _hitActiveTime0.15
  • _staggerDuration1.2(收招后硬直,供玩家反击)

ProjectileAttackAbility(酸液):

  • _configABL_E004_Acid.asset
  • _muzzle:拖入 AcidMuzzle/ Transform
  • ABL_E004_Acid 的 attackSequence[0]
    • clipSkill03.anim
    • projectileCount3(同时发射数量)
    • spreadAngleDeg30(扩散角)
    • projectileFireT0.5Clip 的 50% 时发射)
    • projectileConfig:指向 PROJ_ZhiMu_Acid 的弹体配置 SO

FacePlayerAbility(翻身):

  • _configABL_E004_Flip.asset
  • _faceClipFlip.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 5Addressables

  • AddressENM_ZhiMu · GroupEnemies · LabelsEnemy

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 2ScriptableObject

路径: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 3Prefab

路径:Assets/_Game/Prefabs/Enemies/E005/ENM_FeiZhi.prefab

ENM_FeiZhi (根节点)
├── 组件E005_FeiZhiC# 脚本、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
├── 组件EnemySensorHub
├── 组件Rigidbody2D
├── HurtBox/ → 组件HurtBox
├── BiteHitBox/ → 组件HitBox
├── AcidMuzzle/ → 空 Transform
└── Abilities/
    ├── Bite_Ability → 组件MeleeVulnerabilityAbility
    └── Acid_Ability → 组件ProjectileAttackAbility

E005_FeiZhi 配置

  • _deathPreClipDeath_Pre.anim
  • _hurtBoxHurtBox/ 组件
  • _deathPreDuration:与动画时长一致
  • _spawnCount3(生成 E003 数量,策划调整)
  • _spawnRadius1.5(生成散布半径)

MeleeVulnerabilityAbility撕咬

  • _configABL_E005_Bite.asset
  • _attackClipSkill01.anim
  • _hitBoxBiteHitBox/
  • _hurtBoxHurtBox/(后摇期间开放脆弱窗口)
  • _hitEnterT0.30(攻击 30% 时激活 HitBox
  • _hitExitT0.60(攻击 60% 时停用 HitBox
  • _staggerDuration1.0(后摇脆弱窗口时长,策划调整)

ProjectileAttackAbility酸液连续两次

  • _configABL_E005_Acid.asset
  • _muzzleAcidMuzzle/
  • 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 5Addressables

  • AddressENM_FeiZhi · GroupEnemies · LabelsEnemy

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 跳跃攻击(含起跳/飞行/落地姿态) LeapAttackAbilityattackSequence[0].clip
Death.anim 死亡 AnimConfig.Dead

Step 2ScriptableObject

路径:Assets/_Game/Data/Enemies/E006/

ABL_E006_Leap.asset

字段
abilityId "e006_leap"
cooldown 攻击间隔(策划填写)
attackSequence[0].clip Skill.anim

Step 3Prefab

路径:Assets/_Game/Prefabs/Enemies/E006/ENM_Huan.prefab

ENM_Huan (根节点)
├── 组件EnemyBase、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
├── 组件EnemySensorHub
├── 组件Rigidbody2DDynamic
├── HurtBox/
├── LandingHitBox/ → 组件HitBox落地时的攻击判定
└── Abilities/
    └── Leap_Ability → 组件LeapAttackAbility

EnemyMovement

  • _enableTurnAnimation:勾选 ✓

LeapAttackAbility 配置

  • _configABL_E006_Leap.asset
  • _jumpHeight_maxRange:策划填写
  • _windupTime:起跳前摇时间(秒)
  • _recoveryTime:落地硬直时间
  • _groundMaskGround 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 5Addressables

  • AddressENM_Huan · GroupEnemies · LabelsEnemy

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 2ScriptableObjectBossSkillSO

路径: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.assetHP/速度。

Step 3弹体 Prefab

在制作嘲风 Prefab 之前,需要先创建弹体。

PROJ_Boomerang.prefab

路径:Assets/_Game/Prefabs/Combat/Projectiles/PROJ_Boomerang.prefab

PROJ_Boomerang (根节点)
├── 组件ReturnProjectileC# 脚本,继承 Projectile
├── 组件Rigidbody2DDynamic
├── 组件PooledObject必须用于对象池回收
└── HitBox/ → 组件HitBox、Collider2DLayer=EnemyProjectile

ReturnProjectile 配置

  • _maxRange:最大飞行距离(策划填写)
  • _returnSpeed:返回速度(策划填写)
  • _config:弹体配置 SOProjectileConfigSO,设置 Speed/Lifetime/DamageSource

⚠️ Addressables 配置Address=PROJ_Boomerang, Group=Projectiles, Labels=Poolable, Preload

其他弹体 Prefab

PROJ_TornadoSmallPROJ_TornadoLargePROJ_WindStone:使用现有 Projectile 脚本,配置方式参考项目中已有的弹体。

Step 4搭建嘲风 Prefab

路径:Assets/_Game/Prefabs/Enemies/ChaoFeng/ENM_ChaoFeng.prefab

ENM_ChaoFeng (根节点)
├── 组件ChaoFengBossC# 脚本)
├── 组件EnemyMovement
├── 组件EnemyNavAgent、NavAgent、TransformBasedMovement
├── 组件BossSkillExecutorBoss 技能执行器)
├── 组件ChaoFengFloatController浮空控制器
├── 组件ChaoFengKnockdownCounter击落计数器
├── 组件EnemyFeedback
├── 组件Rigidbody2DDynamic击落/落地时由 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 父类)

  • _statsENM_ChaoFeng_Stats.asset
  • BossSkillExecutor 组件中,添加所有 5 个 BossSkillSOBoomerang/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_stoneavailablePhaseIndices=[1]
│       └── BD_Wait → Duration: 0.5
│
└── Selector [Phase 1 地面战斗]   ← HP > 50% 时走此分支
    ├── BD_UseBossSkillWeighted  ← 4 个 Phase 0 技能加权随机
    └── BD_MoveToPlayer

⚠️ 关键架构说明

  • BD_BossPhaseTransition 必须位于 Phase 2 Sequence 的中间,而非独立的并列节点。
  • 过渡完成后(CurrentPhase>=1BD_BossPhaseTransition 每 tick 立即返回 SuccessSequence 继续执行下方的战斗节点。
  • 若两者为并列节点,过渡完成后父 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 6Addressables

  • AddressENM_ChaoFeng · GroupBoss_ChaoFeng · Labels不加 Enemy 标签

11. Addressables 注册步骤

  1. 打开 Window → Asset Management → Addressables → Groups
  2. 找到对应 GroupEnemies / 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. 常见错误排查

技能触发后动画不播放

原因:能力 SOEnemyAbilitySOattackSequenceclip 字段未绑定 Clip或 Ability 组件上的 ClipTransition 字段未绑定。
修复:检查 Inspector确认所有 ClipTransition 字段已拖入对应 .anim 文件。


BD_UseAbility 没有效果(技能没有执行)

原因 AAbility 组件没有挂在子节点,而是挂在根节点本身。
修复:将 Ability 组件移到 Abilities/ 子节点。

原因 BabilityId 与 SO 中的 abilityId 不一致(大小写或拼写错误)。
修复:对照 SO 的 abilityId 字段,确认拼写完全一致。


E003 出现后不下落

原因 AAnimatedCeilingDropAbility._groundMask 未设置,导致落地检测失败,能力超时后强制结束。
修复:将 Ground Layer 加入 _groundMask

原因 BE003_YouZhi._activateOnSpawn 未勾选(对象池路径无法触发下落)。
修复:在 Inspector 勾选 _activateOnSpawn


E005 死亡后没有生成 E003

原因 ADeath_Pre.anim 中没有 AnimationEvent或函数名/参数拼写错误。
修复:打开动画编辑器,确认 AnimationEvent 的函数为 SpawnProjectile,参数为 "spawn_e003"(区分大小写)。

原因 BENM_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 秒)。


回旋扇飞出后不回来

原因 AReturnProjectile.SetOwner() 没有被调用,_ownerTransform 为 null。
验证:确认 ChaoFengBoss.SpawnProjectile("boomerang") 中调用了 go.GetComponent<ReturnProjectile>()?.SetOwner(transform)。这是 C# 代码,程序检查,策划确认 AnimationEvent 的 payload 拼写正确("boomerang" 全小写)。

原因 BPROJ_Boomerang 的 Prefab 根节点没有挂 PooledObject 组件。
修复:添加 PooledObject 组件。


如遇到本文档未涵盖的问题,请联系程序查看 Docs/Plan/小怪与Boss实现计划-01.md 中的架构关键约束章节,或查阅 Docs/Architecture/07_EnemyModule.md