Files
zeling_v2/Docs/Design/06_EnemySystem.md
2026-05-08 11:04:00 +08:00

15 KiB
Raw Permalink Blame History

06 · 敌人系统

命名空间 BaseGames.Enemies · BaseGames.Enemies.AI · BaseGames.Enemies.Navigation
所属文档集 ← 返回索引 · 总览
依赖 BaseGames.Combat · Behavior Designer Pro · PathBerserker2d


目录

  1. 系统总览
  2. EnemyBase — 敌人基础组件
  3. EnemyStatsSO — 敌人属性配置
  4. 敌人状态机
  5. Behavior Designer 任务目录
  6. 标准行为树模板
  7. Boss 行为树模板
  8. PathBerserker2d 导航集成
  9. BossBase — Boss 特化设计
  10. 敌人 Prefab 层级结构
  11. EnemyAnimationConfigSO
  12. 编辑器友好设计

1. 系统总览

敌人系统由三个层次组成:

EnemyBaseMonoBehaviour协调器
├── EnemyStats            ← 运行时属性HP、防御等
├── EnemyMovement         ← Rigidbody2D 移动封装
├── EnemyAnimator         ← Animancer 动画(单层)
├── EnemyCombat           ← HitBox 管理
├── EnemyNavAgent         ← PathBerserker2d 寻路封装
└── BehaviorTree          ← Behavior Designer 行为树AI 决策)

组件关系:
  BehaviorTreeWhat to do → EnemyBase接口 → EnemyMovement/EnemyCombat/EnemyNavAgentHow to do it
  BD 任务通过 SharedVariable 访问 EnemyBase 接口,不直接操作 Rigidbody2D

2. EnemyBase — 敌人基础组件

EnemyBase 是所有敌人的基础,暴露给 BD 任务的接口列表

移动接口

方法 调用方BD任务 说明
MoveTo(Vector2 target) BD_MoveTo 通过 NavAgent 移动到目标点
MoveInDirection(float dir) BD_Patrol 直接控制水平移动方向(无寻路)
StopMovement() BD_StopMovement 立即停止移动
JumpTo(Vector2 target) BD_Jump 施加跳跃冲量朝向目标
Knockback(DamageInfo) HurtBox 受击击退(不由 BD 控制)
FacePlayer() BD_FaceTarget 翻转 SpriteRenderer 朝向玩家

战斗接口

方法 调用方BD任务 说明
BeginAttack(AttackType type) BD_Attack 开始攻击(激活对应 HitBox
CanAttack() BD_CanAttack 检查攻击是否冷却完毕
IsPlayerInRange(float range) BD_IsInRange 检测玩家是否在攻击范围内
IsPlayerVisible() BD_IsVisible Raycast 检测玩家是否可见

状态接口

方法/属性 说明
ForceState(EnemyStateType) 强制切换敌人状态Stagger/Death 等)
TakeDamage(DamageInfo) 接受伤害(由 HurtBox 调用)
IsDead 是否已死亡(只读)
IsStaggered 是否处于硬直中(只读)
CurrentHP 当前 HP只读供 BD Conditional 使用)

3. EnemyStatsSO — 敌人属性配置

EnemyStatsSO 继承自 ScriptableObject,每类敌人一份资产:

字段 类型 说明
DisplayName string 敌人名称UI显示
MaxHP int 最大生命值
DefenseStat int 防御减免值
WalkSpeed float 行走速度
RunSpeed float 追击速度
DetectionRange float 玩家检测半径
AttackRange float 攻击触发范围
AttackCooldown float 攻击冷却时间
GeoDropAmount int 死亡时掉落 Geo
GeoDropVariance int Geo 掉落随机浮动量
StaggerResistance float Stagger 抗性0=正常1=免疫)
PatrolDistance float 巡逻范围(从出生点起)

资产存放路径

Assets/ScriptableObjects/Enemies/Stats/

命名规范:ES_{EnemyName}.asset,如 ES_GruntWarrior.assetES_SkullArcher.asset


4. 敌人状态机

EnemyBase 内部维护轻量状态枚举(不使用 Animancer FSMBD 行为树处理大部分逻辑):

状态 说明 优先级
Dead 已死亡,所有系统停用 最高
Stagger 弹反/强击后硬直 90
Hurt 受击硬直 80
Controlled BD 行为树正常控制 10

EnemyBase.State != ControlledBehaviorTree 暂停执行(调用 BehaviorTree.DisableBehavior())。


5. Behavior Designer 任务目录

Action Tasks

任务类名 命名空间 说明
BD_MoveTo BaseGames.Enemies.AI 通过 NavAgent 移动到 SharedTransform target
BD_MoveToPlayer BaseGames.Enemies.AI 持续追踪玩家位置
BD_Patrol BaseGames.Enemies.AI 在巡逻区间来回移动(非寻路,直接控制速度)
BD_FacePlayer BaseGames.Enemies.AI 翻转 Sprite 朝向玩家
BD_Wait BaseGames.Enemies.AI 等待 SharedFloat duration 秒(Success 后)
BD_WaitRandom BaseGames.Enemies.AI 随机等待 min~max 秒
BD_Attack BaseGames.Enemies.AI 执行攻击(激活 HitBox播放攻击动画
BD_PlayAnimation BaseGames.Enemies.AI 播放指定 AnimancerState
BD_StopMovement BaseGames.Enemies.AI 立即停止移动
BD_SetAlert BaseGames.Enemies.AI 设置 SharedBool isAlerted 为 true触发警觉动画
BD_SpawnProjectile BaseGames.Enemies.AI 从挂载点生成弹射物
BD_TeleportTo BaseGames.Enemies.AI 瞬移到指定位置Boss 特殊移动)

Conditional Tasks

任务类名 说明 返回值
BD_IsPlayerInRange 玩家是否在攻击范围内 Success / Failure
BD_IsPlayerVisible Raycast 检测玩家可见性 Success / Failure
BD_CanAttack 攻击是否冷却完毕 Success / Failure
BD_IsHPBelow HP 是否低于阈值(SharedFloat threshold Success / Failure
BD_IsPlayerOnSamePlatform 玩家是否在同一平台上 Success / Failure
BD_IsPatrolComplete 巡逻是否到达端点 Success / Failure
BD_IsAlerted 是否处于警觉状态 Success / Failure

BD SharedVariables 规范

所有 BD 行为树中使用的 SharedVariable 命名约定(保持所有敌人一致):

变量名 类型 说明
playerTransform SharedTransform 玩家 Transform由 EnemyBase 注入)
selfTransform SharedTransform 自身 Transform
patrolPointA SharedVector2 巡逻起点
patrolPointB SharedVector2 巡逻终点
isAlerted SharedBool 是否警觉
targetPosition SharedVector2 当前寻路目标
hpThreshold SharedFloat HP 百分比阈值Boss 换相用)

6. 标准行为树模板

模板 A巡逻-警觉-追击-攻击(近战普通敌人)

[Selector]
  │
  ├─ [Sequence] — 死亡检测(优先级最高)
  │    └─ [Conditional] BD_IsHPBelow(0) → Running触发 Dead 状态BD 暂停)
  │
  ├─ [Sequence] — 追击并攻击
  │    ├─ [Conditional] BD_IsPlayerVisible
  │    ├─ [Action] BD_FacePlayer
  │    ├─ [Selector] — 攻击或追击
  │    │    ├─ [Sequence] — 攻击
  │    │    │    ├─ [Conditional] BD_IsPlayerInRange
  │    │    │    ├─ [Conditional] BD_CanAttack
  │    │    │    ├─ [Action] BD_StopMovement
  │    │    │    └─ [Action] BD_Attack
  │    │    └─ [Action] BD_MoveToPlayer  — 追击
  │    └─ [Action] BD_SetAlert
  │
  └─ [Sequence] — 巡逻
       ├─ [Action] BD_Patrol
       └─ [Action] BD_WaitRandom(1.0, 2.5)

模板 B弓箭手远程攻击

[Selector]
  ├─ [Sequence] — 远程攻击
  │    ├─ [Conditional] BD_IsPlayerVisible
  │    ├─ [Action] BD_FacePlayer
  │    ├─ [Action] BD_StopMovement
  │    ├─ [Conditional] BD_CanAttack
  │    └─ [Action] BD_SpawnProjectile
  │
  ├─ [Sequence] — 保持距离
  │    ├─ [Conditional] BD_IsPlayerInRange(3.0)  ← 太近则后退
  │    └─ [Action] BD_MoveInDirection(-1)  ← 后退
  │
  └─ [Action] BD_Patrol

7. Boss 行为树模板

Boss 使用多阶段结构,BD_IsHPBelow 控制阶段切换:

[Selector]
  │
  ├─ [Sequence] — 阶段二HP < 40%
  │    ├─ [Conditional] BD_IsHPBelow(0.4)
  │    └─ [Subtree] BossPhase2BehaviorTree
  │
  ├─ [Sequence] — 阶段一(默认)
  │    └─ [Subtree] BossPhase1BehaviorTree
  │
  └─ [Action] BD_Wait(99)  ← 异常保底(不应到达)

BossPhase1BehaviorTree子树

[Selector]
  ├─ [Sequence] — 近距攻击
  │    ├─ [Conditional] BD_IsPlayerInRange(2.5)
  │    ├─ [Conditional] BD_CanAttack
  │    └─ [Action] BD_Attack(AttackType.MeleeCombo)
  │
  ├─ [Sequence] — 远程技能
  │    ├─ [Conditional] BD_CanAttack
  │    ├─ [Action] BD_StopMovement
  │    └─ [Action] BD_Attack(AttackType.RangedSkill)
  │
  └─ [Action] BD_MoveToPlayer

8. PathBerserker2d 导航集成

EnemyNavAgent 是对 PathBerserker2d NavAgent 的封装,向 BD 任务提供简洁接口:

NavSurface 场景配置

每个场景必须配置:

[NavMesh] (Scene Root GameObject)
├── NavSurface               ← PathBerserker2d 导航面
│   ├── Layer Mask: Ground, Platform, OneWayPlatform
│   └── Agent Radius: 0.3(按最小敌人尺寸)
└── NavLink_Platform_01      ← 平台跳跃链接(手动放置)
    NavLink_Platform_02
    ...

NavSurface 烘焙时机

  • 编辑时(静态场景):在 Unity Editor 中提前烘焙并保存
  • 运行时动态场景P1调用 NavSurface.BuildNavMesh() 动态重烘焙
NavLink 类型 使用场景 配置参数
Jump 从平台跳到下方平台 MaxFallHeightJumpForce
DropDown 穿越单向平台下落 OneWayPlatformLayer
LedgeGrab 抓爬台阶P1 ClimbHeight

EnemyNavAgent 封装接口

方法 说明
RequestMoveTo(Vector2 dest) 请求寻路到目标,异步开始
StopNavigation() 停止寻路,清空路径
IsAtDestination() 是否到达目标点(误差 < 0.2 units
OnNavPathFailed UnityEvent寻路失败时触发切换为直接追击

寻路失败容错:若 PathBerserker2d 无法找到路径,EnemyNavAgent.OnNavPathFailed 触发BD 行为树退化为简单的水平追击(BD_MoveInDirection)。


9. BossBase — Boss 特化设计

BossBase 继承 EnemyBase,新增以下机制:

BossPhaseConfigSO

每个 Boss 阶段独立 SO 资产,便于策划调整:

字段 类型 说明
PhaseIndex int 阶段编号从1开始
HPThreshold float 进入此阶段的 HP 百分比0~1
BehaviorTreeAsset ExternalBehaviorTree 该阶段使用的 BD 行为树资产
MusicTrack AudioClip 阶段背景音乐
PhaseTransitionFeedback MMF_Player 换相时播放的 Feel 反馈(特效/震动)

血量分段显示

BossHPBar 根据 BossPhaseConfigSO[] 绘制血量分段线,玩家可在 UI 中预判换相位置。

BossArena 配置

[BossArena] (Scene GameObject)
├── ArenaCollider           ← PolygonCollider2D限制玩家退出 Boss 房间
├── BossSpawnPoint          ← Boss 出生点
├── [CameraBounds_Boss]     ← 专属 Cinemachine Confiner固定大视野
└── BossRoomTrigger         ← OnTriggerEnter2D 触发 Boss 战开始
    └─ 发布 OnBossFightStarted 事件频道

10. 敌人 Prefab 层级结构

[Enemy_GruntWarrior] (Prefab)
├── SpriteRenderer
├── AnimancerComponent
├── Rigidbody2D (Body Type: Dynamic, Freeze Rotation Z)
├── CapsuleCollider2D (物理碰撞)
│
├── [HurtBox]
│   ├── BoxCollider2D (IsTrigger, Layer: EnemyHurtBox)
│   └── HurtBox.cs
│
├── [HitBox_Melee]
│   ├── BoxCollider2D (IsTrigger, Layer: EnemyAttack)
│   └── HitBox.cs
│       └── _damageSource: ES_GruntWarrior_Melee.asset
│
├── [DetectionRange]
│   └── CircleCollider2D (IsTrigger, 半径 = DetectionRange)
│
├── EnemyBase.cs
├── EnemyStats.cs         ← 持有 EnemyStatsSO 引用
├── EnemyMovement.cs
├── EnemyAnimator.cs
├── EnemyCombat.cs
├── EnemyNavAgent.cs      ← 持有 NavAgent 引用
├── BehaviorTree.cs       ← 持有 BehaviorTreeAsset 引用
└── EnemyFeedback.cs      ← 持有 MMF_Player 引用

11. EnemyAnimationConfigSO

每类敌人配置独立的 EnemyAnimationConfigSO(存放于 Assets/ScriptableObjects/Enemies/Animations/

字段名 说明
Idle 待机循环动画
Walk 行走循环
Run 奔跑循环
Alert 警觉动画(发现玩家时)
Attack_Melee 近战攻击
Attack_Ranged 远程攻击(弓箭手/法师)
Hurt 受击动画
Stagger 弹反硬直
Death 死亡动画(播放一次后保持最后帧)

12. 编辑器友好设计

EnemyBase 自定义 Inspector

┌─ EnemyBase ─────────────────────────────────────┐
│  State    : Controlled                          │
│  HP       : █████████░░░  75 / 100             │
│  Alerted  : ✓                                   │
│  Nav Path : Active → Room_Forest_01 (0.8m)      │
│  ─────────────────────────────────────────────  │
│  BD Tree  : [GruntWarrior_Patrol.asset]         │
│             [当前执行节点: BD_MoveToPlayer]      │
│  ─────────────────────────────────────────────  │
│  [强制Stagger 0.8s] [强制Death] [重置HP] [重置BD]│
└─────────────────────────────────────────────────┘

Scene 视图 Gizmos

Gizmo 颜色 说明
检测范围 黄色圆圈 DetectionRange 球形范围
攻击范围 红色圆圈 AttackRange 球形范围
巡逻路径 蓝色线段 patrolPointApatrolPointB 连线
寻路目标 绿色箭头 指向当前 NavAgent 目标点
HitBox 橙色矩形 攻击判定区域(激活时实心,未激活时虚线)
HurtBox 绿色矩形 受击区域
视线检测 青色射线 IsPlayerVisible 使用的 Raycast