12 KiB
手动测试 08 · 敌人系统
测试类型:Unity Editor 手动测试(Play Mode)
覆盖模块:BaseGames.Enemies、BaseGames.Enemies.AI、BaseGames.Enemies.Navigation
依赖组件:EnemyBase、EnemyCombat、EnemyMovement、BehaviorDesigner、PathBerserker2d
场景要求:已烘焙 NavSurface,至少包含近战/远程/飞行三种敌人各一只
快速工具
| 工具 | 用途 | 菜单路径 |
|---|---|---|
| Place Enemy (Basic) | 放置带 EnemyBase、EnemyStats、HurtBox、HitBox_Body 的基础敌人;多次调用可摆放多种变体,然后手动调整组件 | BaseGames → Scene → Place → Enemy (Basic) |
| Place Nav Surface | 在场景中放置 PathBerserker2d NavSurface 对象 | BaseGames → Scene → Place → Nav Surface |
| Place Ground Platform | 放置地面平台(Layer=Ground) | BaseGames → Scene → Place → Ground Platform |
NavSurface 烘焙:在 Inspector 中找到
NavSurface组件,点击 Bake 按钮(无对应菜单命令)。
注意:PlayModeDebugOverlay 已移除。运行时状态效果测试请通过配置带效果的敌人攻击,或代码调用StatusEffectManager.Apply()。
典型工作流:
- 测试前:
Place → Ground Platform生成地面 +Place → Enemy (Basic)放置近战 / 远程 / 飞行三种敌人(多次调用,手动调整组件和配置)。 - Add Enemy Variants:
Place → Enemy (Basic)多次,分别调整EnemyStats和行为树为远程 / 飞行变体。 - Inspector NavSurface → Bake 烘焙寻路数据(相比手动查找 Inspector 更直接)。
- 状态效果测试(
MT-ENEMY-04):配置带毒/燃烧效果的敌人攻击,或通过代码调用;观察 VFX 变化和 Console 事件。
目录
- NavSurface 烘焙检查
- MT-ENEMY-01:近战敌人 AI 基础行为
- MT-ENEMY-02:远程敌人(RangedEnemy)
- MT-ENEMY-03:飞行敌人(FlyingEnemy)
- MT-ENEMY-04:敌人霸体与击退
- MT-ENEMY-05:敌人死亡与掉落
- MT-ENEMY-06:敌人配额管理
- MT-ENEMY-07:Boss 战切换流程
1. NavSurface 烘焙检查
PathBerserker2d 的寻路完全依赖烘焙数据,未烘焙时敌人原地站立无响应。
🔧 敌人场景快速搭建
BaseGames → Scene → Place → Ground Platform生成地面 +Place → Player放置玩家(若尚未搭建)
BaseGames → Scene → Place → Enemy (Basic)多次调用,放置近战 / 远程 / 飞行三种敌人:
- MeleeEnemy:保持默认配置(EnemyBase + EnemyStats + EnemyMovement + HurtBox)
- RangedEnemy:手动添加
ShootPoint子 GameObject,调整 EnemyStats 为远程变体 SO- FlyingEnemy:手动修改 Rigidbody2D → Kinematic,
gravityScale = 0三只敌人均需在 Inspector 中绑定 Behavior Designer 行为树资产(
BehaviorTree._externalBehavior字段)Inspector NavSurface 组件 → 点击 Bake 烘焙近战 + 远程敌人的寻路数据
注意:
FlyingEnemy无需 NavSurface 寻路;RangedEnemy需要 NavSurface 才能进行保距移动。
检查步骤:
- 在测试场景中选中挂有
NavSurface组件的 GameObject - Inspector 中找到
NavSurface组件,点击 Bake - Scene 视图中地面显示蓝绿色半透明网格 → 烘焙成功
提示:若 Gizmo 不可见,点击 Scene 视图右上角 Gizmos → 确认 PathBerserker2d 相关项已勾选。
MT-ENEMY-01:近战敌人 AI 基础行为
目的:验证近战敌人的巡逻 → 追击 → 攻击 → 返回 Behavior Designer 行为树。
🔧 前置检查
Place → Enemy (Basic)已放置MeleeEnemy并挂载所有必要组件- Inspector 中
BehaviorTree._externalBehavior字段已绑定行为树资产(手动拖入)- NavSurface 已烘焙(Inspector → Bake 按钮)
步骤
步骤 A:巡逻行为
- 进入 Play Mode
- 玩家保持在敌人视野范围外(超过
detectionRange) - 观察敌人
预期:
- 敌人在巡逻点之间来回移动
- 播放
Walk/Patrol动画 - Console 无 PathBerserker2d 寻路错误
步骤 B:追击行为
- 玩家进入敌人视野(
detectionRange内且无遮挡物) - 观察敌人反应
预期:
- 敌人停止巡逻,转向玩家方向
- 播放
Run/Chase动画 - 以最优路径追击玩家(PathBerserker2d 动态路径)
步骤 C:攻击行为
- 玩家进入敌人攻击范围(
attackRange内) - 观察敌人攻击
预期:
- 播放攻击动画(Behavior Designer 行为树触发攻击节点)
EnemyCombat.HitBox激活,若玩家在判定范围内触发伤害- 攻击后进入冷却(
attackCooldown)
步骤 D:掉失目标后返回
- 玩家跑出敌人追击范围(
chaseRange外) - 观察敌人
预期:
- 敌人停止追击,返回初始位置或巡逻路径
- 返回后恢复巡逻动画
| 检查点 | 期望 | ✓ |
|---|---|---|
| 巡逻动画 | 视野外敌人来回巡逻 | ☐ |
| 追击切换 | 玩家进入视野后立即追击 | ☐ |
| 攻击命中 | 攻击范围内玩家 HP 减少 | ☐ |
| 返回巡逻 | 丢失目标后返回初始位置 | ☐ |
| 无寻路错误 | Console 无 PathBerserker2d 相关 Error | ☐ |
MT-ENEMY-02:远程敌人(RangedEnemy)
目的:验证 RangedEnemy 的投射物发射、移动闪避、最优射击位置。
🔧 前置检查
BaseGames → Scene → Place → Enemy (Basic)已放置RangedEnemy(调整 EnemyStats 为远程变体,位置 x=8)- Inspector 中为
RangedEnemy配置行为树资产(保距 + LOS 检测 + 发射节点)RangedEnemy._shootPoint子 Transform 已手动添加- 场景有静止障碍物(
Place → Obstacle (Static))以便观察子弹碰撞
步骤
- 确认测试场景中有
RangedEnemy实例(挂有EnemyCombat组件) - 进入 Play Mode,玩家接近远程敌人
步骤 A:保持距离
预期:远程敌人尝试保持在 preferredDistance 附近,玩家靠近时后退。
步骤 B:发射投射物
预期:
- 在
shootRange内发射投射物(LinearProjectile或ArcProjectile) - 投射物从
_shootPointTransform 位置发出 - 命中玩家触发伤害
步骤 C:LOS(视线)检测
- 让玩家躲在墙壁后面(无视线)
- 观察远程敌人是否仍然发射
预期:无视线时,敌人停止发射(LOS 检测生效)。
| 检查点 | 期望 | ✓ |
|---|---|---|
| 保持距离 | 玩家靠近时后退 | ☐ |
| 发射投射物 | 视线内发射子弹命中玩家 | ☐ |
| LOS 遮挡 | 墙后无视线时停止发射 | ☐ |
MT-ENEMY-03:飞行敌人(FlyingEnemy)
目的:验证 FlyingEnemy 的空中移动、俯冲攻击、不受地面 NavSurface 约束。
🔧 前置检查
BaseGames → Scene → Place → Enemy (Basic)已放置FlyingEnemy(位置 (3,5,0))Rigidbody2D.gravityScale = 0,bodyType = Kinematic(手动在 Inspector 设置)- 配置行为树资产(直线追击 + 俯冲攻击,无需 NavSurface)
步骤
- 确认场景有
FlyingEnemy实例(Kinematic RB,gravityScale=0) - 进入 Play Mode
步骤 A:空中悬停/巡逻
预期:
- 飞行敌人在空中自由移动,不受地形限制
- 可以穿越平台上下(不像地面敌人需要寻路绕路)
步骤 B:俯冲攻击
预期:
- 锁定玩家后俯冲攻击
- 攻击后飞回起始高度,继续攻击循环
步骤 C:不被地面碰撞阻挡
- 让飞行敌人在追击路径中有地形障碍
预期:飞行敌人从障碍物上方飞过(不被地面碰撞体阻挡)。
| 检查点 | 期望 | ✓ |
|---|---|---|
| 空中自由移动 | 不受地面寻路限制 | ☐ |
| 俯冲攻击 | 正确识别玩家位置并俯冲 | ☐ |
| 绕过地形 | 从障碍上方飞过 | ☐ |
MT-ENEMY-04:敌人霸体与击退
目的:验证 EnemyPoiseComponent 在普通攻击下保持动画,重攻击才打断。
步骤
步骤 A:普通连击不打断
- 对有较高霸体的敌人进行连击
预期:若连击伤害低于霸体 breakLevel,敌人动画不被打断,继续执行 AI 行为。
步骤 B:重攻击打断
- 对同一敌人使用
BreakLevel高的攻击(如下劈DownAttack或特殊技能)
预期:敌人进入受击硬直,AI 行为树暂停。
步骤 C:击退效果
- 攻击有击退(
knockbackForce > 0)的攻击
预期:敌人被击退一定距离(knockbackForce 方向与大小),不会穿墙。
| 检查点 | 期望 | ✓ |
|---|---|---|
| 普通攻击不打断 | 霸体保护时 AI 行为继续 | ☐ |
| 重攻击打断 | BreakLevel > Poise 时触发硬直 | ☐ |
| 击退物理 | 被击退后不穿越地形 | ☐ |
MT-ENEMY-05:敌人死亡与掉落
目的:验证敌人 HP 归零后的死亡流程、Geo 掉落、LootResolver。
步骤
- 将敌人 HP 降至 0
预期:
- 死亡动画播放
- 死亡动画结束后 GameObject 从场景移除(或
SetActive(false)归还对象池) LootTableSO根据权重随机掉落 Geo 或其他物品
- 在掉落的 Geo 上移动玩家
预期:Geo 被拾取,玩家 CurrentGeo 增加,HUD Geo 数量更新。
- 重新进入场景(房间切换后返回)
预期:根据 WorldStateRegistry 配置,死亡敌人是否重生(可配置的一次性/可重生区别)。
| 检查点 | 期望 | ✓ |
|---|---|---|
| 死亡动画 | HP 归零后播放死亡动画 | ☐ |
| 清理 | 动画结束后 GameObject 消失或归池 | ☐ |
| Geo 掉落 | 掉落 Geo 可拾取,HUD 更新 | ☐ |
| LootTable | 掉落物符合权重概率 | ☐ |
MT-ENEMY-06:敌人配额管理
目的:验证 EnemyQuotaManager 限制同屏激活敌人数量,防止性能劣化。
步骤
- 打开 Inspector,找到场景中的
EnemyQuotaManager - 记录当前
maxActiveEnemies配置值(如 8) - 进入 Play Mode,触发大量敌人(通过多个 EnemySpawner)
预期:
- 同屏激活的敌人不超过
maxActiveEnemies - 超出配额的敌人保持待机(Deactivate 或等待)
- 当已激活敌人死亡后,待机敌人激活补充
| 检查点 | 期望 | ✓ |
|---|---|---|
| 不超过配额 | 激活敌人数量 ≤ maxActiveEnemies | ☐ |
| 死亡后补充 | 敌人死亡后待机敌人激活 | ☐ |
MT-ENEMY-07:Boss 战切换流程
目的:验证 Boss 战触发的 GameState 切换(Gameplay → BossFight)、Boss 血条 UI 显示。
步骤
- 进入有 Boss 触发器的场景或房间
- 玩家进入 Boss 房间触发器
预期:
EVT_BossFightStarted事件触发(EventBusMonitor 可见)GameManager状态切换到BossFight- Boss HP 血条 UI 出现(大型 HP 条 + Boss 名称文字)
- 背景音乐切换为 Boss 战曲目
- 将 Boss HP 降至 0
预期:
EVT_BossFightEnded事件触发(victory = true)- GameManager 切回
Gameplay状态 - Boss 血条 UI 隐藏
- 胜利 VFX/音效播放
| 检查点 | 期望 | ✓ |
|---|---|---|
| Boss 战触发 | 进入触发器后 GameState = BossFight | ☐ |
| Boss HP 条 | Boss 血条 UI 正确显示 | ☐ |
| BGM 切换 | 战斗音乐正确播放 | ☐ |
| Boss 死亡 | 胜利后状态恢复 Gameplay | ☐ |
| BossProgressTracker | Console 中 Boss 击败状态记录 | ☐ |