# 06 · 敌人系统 > **命名空间** `BaseGames.Enemies` · `BaseGames.Enemies.AI` · `BaseGames.Enemies.Navigation` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **依赖** `BaseGames.Combat` · Behavior Designer Pro · PathBerserker2d --- ## 目录 1. [系统总览](#1-系统总览) 2. [EnemyBase — 敌人基础组件](#2-enemybase--敌人基础组件) 3. [EnemyStatsSO — 敌人属性配置](#3-enemystatsso--敌人属性配置) 4. [敌人状态机](#4-敌人状态机) 5. [Behavior Designer 任务目录](#5-behavior-designer-任务目录) 6. [标准行为树模板](#6-标准行为树模板) 7. [Boss 行为树模板](#7-boss-行为树模板) 8. [PathBerserker2d 导航集成](#8-pathberserker2d-导航集成) 9. [BossBase — Boss 特化设计](#9-bossbase--boss-特化设计) 10. [敌人 Prefab 层级结构](#10-敌人-prefab-层级结构) 11. [EnemyAnimationConfigSO](#11-enemyanimationconfigso) 12. [编辑器友好设计](#12-编辑器友好设计) --- ## 1. 系统总览 敌人系统由三个层次组成: ``` EnemyBase(MonoBehaviour,协调器) ├── EnemyStats ← 运行时属性(HP、防御等) ├── EnemyMovement ← Rigidbody2D 移动封装 ├── EnemyAnimator ← Animancer 动画(单层) ├── EnemyCombat ← HitBox 管理 ├── EnemyNavAgent ← PathBerserker2d 寻路封装 └── BehaviorTree ← Behavior Designer 行为树(AI 决策) 组件关系: BehaviorTree(What to do) → EnemyBase接口 → EnemyMovement/EnemyCombat/EnemyNavAgent(How 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.asset`、`ES_SkullArcher.asset`。 --- ## 4. 敌人状态机 `EnemyBase` 内部维护轻量状态枚举(不使用 Animancer FSM,BD 行为树处理大部分逻辑): | 状态 | 说明 | 优先级 | |------|------|--------| | `Dead` | 已死亡,所有系统停用 | 最高 | | `Stagger` | 弹反/强击后硬直 | 90 | | `Hurt` | 受击硬直 | 80 | | `Controlled` | BD 行为树正常控制 | 10 | 当 `EnemyBase.State != Controlled` 时,BehaviorTree 暂停执行(调用 `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 类型规范 | NavLink 类型 | 使用场景 | 配置参数 | |-------------|---------|---------| | `Jump` | 从平台跳到下方平台 | `MaxFallHeight`、`JumpForce` | | `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` 球形范围 | | 巡逻路径 | 蓝色线段 | `patrolPointA` ↔ `patrolPointB` 连线 | | 寻路目标 | 绿色箭头 | 指向当前 NavAgent 目标点 | | HitBox | 橙色矩形 | 攻击判定区域(激活时实心,未激活时虚线)| | HurtBox | 绿色矩形 | 受击区域 | | 视线检测 | 青色射线 | `IsPlayerVisible` 使用的 Raycast |