chore: initial commit

This commit is contained in:
2026-05-08 11:04:00 +08:00
commit f55d2a57c3
6278 changed files with 866081 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
# 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. 系统总览
敌人系统由三个层次组成:
```
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.asset``ES_SkullArcher.asset`
---
## 4. 敌人状态机
`EnemyBase` 内部维护轻量状态枚举(不使用 Animancer FSMBD 行为树处理大部分逻辑):
| 状态 | 说明 | 优先级 |
|------|------|--------|
| `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 |