refactor(enemy): 敌人专属子类改为零代码配置型行为组件
This commit is contained in:
@@ -92,9 +92,12 @@ public class EnemyBase : MonoBehaviour, IDamageable
|
||||
|
||||
// ──── EnemyAnimationEvents 接口(虚方法,Boss 子类覆盖)──────────
|
||||
// 由 EnemyAnimationEvents.OnAnimationEvent 在对应动画帧触发时调用(见 24_AnimEventModule §6)
|
||||
public virtual void SpawnProjectile(string data) { }
|
||||
// SpawnProjectile 基类实现:路由到挂载的 IEnemySpawnEventHandler 组件(见 §8.5 配置型行为组件)
|
||||
public virtual void SpawnProjectile(string data) { /* routes to IEnemySpawnEventHandler */ }
|
||||
public virtual void TriggerPhaseTwo() { }
|
||||
public virtual void OnAnimationComplete(string data) { }
|
||||
// 对象池取出并完成 OnSpawn 重置后触发;配置型出生行为组件(EnemyAbilityTrigger)订阅
|
||||
public event System.Action Spawned;
|
||||
// ⚡ BD 每帧 Tick 调用 Blackboard 读写 SharedVariable;Awake 缓存、消除 GetComponent 热开销
|
||||
public BehaviorTree Blackboard => _behaviorTree;
|
||||
|
||||
@@ -426,6 +429,20 @@ public class EnemyAnimationConfigSO : ScriptableObject
|
||||
|
||||
---
|
||||
|
||||
## 8.5 配置型行为组件(零代码扩展点)
|
||||
|
||||
过去 E003/E004/E005 等敌人各写一个继承 `EnemyBase` 的专属子类,只为挂接少量生命周期钩子。现已抽成**通用、可配置的行为组件**——策划在 Prefab 上加组件、填字段即可,不再为单个敌人写脚本。`EnemyBase` 在 `Awake` 收集这些组件并在对应时机回调。
|
||||
|
||||
| 组件 | 命名空间 | 作用 | 关键字段 | 接入的 EnemyBase 钩子 |
|
||||
|------|---------|------|---------|---------------------|
|
||||
| `EnemyAbilityTrigger` | `BaseGames.Enemies.Behaviors` | 出生时(对象池)或外部时机执行某个能力 | `_abilityId`、`_executeOnSpawn` | 订阅 `Spawned` 事件;`public Trigger()` 供场景触发器/UnityEvent/动画事件调用 |
|
||||
| `EnemyDeathSequence` | 同上 | 死亡前摇无敌演出(停 BT/移动、关 HurtBox、播放前摇、等待后再真正死亡) | `_deathPreClip`、`_duration`、`_hurtBoxesToDisable` | 实现 `IEnemyDeathSequence`;`Die()` 委托其播放,期间 `IsInvincible=true`,结束回调 `PerformDeath()` |
|
||||
| `EnemySpawnerOnEvent` | 同上 | 动画事件触发的对象池生成(如死亡演出中生成小怪) | `_payloadKey`、`_poolKey`、`_count`、`_radius` | 实现 `IEnemySpawnEventHandler`;`SpawnProjectile(payload)` 路由匹配 |
|
||||
|
||||
扩展原则:新的"某时机做某事"需求优先做成此类通用组件(参考现有 `AssignReference`/`AssignAsset` 脚手架绑定模式接入 `SceneObjectPlacerTool`),而非新建 `EnemyBase` 子类——使敌人尽量通过配置而非代码创建。`RangedEnemy` / `BossBase` / `ChaoFengBoss` 等仍可重写 `SpawnProjectile`/`Die` 自定义逻辑(重写不调用 base 时即绕过路由/委托)。
|
||||
|
||||
---
|
||||
|
||||
## 9. BossBase
|
||||
|
||||
```csharp
|
||||
|
||||
@@ -404,7 +404,7 @@ Selector
|
||||
|
||||
```
|
||||
ENM_YouZhi (根节点)
|
||||
├── 组件:E003_YouZhi(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemyBase、EnemyAbilityTrigger、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemySensorHub
|
||||
├── 组件:Rigidbody2D(初始 Body Type=Kinematic,下落能力会自动切换为 Dynamic)
|
||||
├── HurtBox/
|
||||
@@ -426,8 +426,10 @@ ENM_YouZhi (根节点)
|
||||
| `_recoveryTime` | `0.1`(落地后短暂停顿) |
|
||||
| `_contactDamage` | 拖入 `ContactDamageZone/` 的 BodyContactDamage |
|
||||
|
||||
**E003_YouZhi 组件配置**:
|
||||
- `_activateOnSpawn`:勾选 ✓(对象池生成时自动触发下落;若是场景预置则由触发器调用 `ActivateFromCeiling()` 方法)
|
||||
**EnemyAbilityTrigger 组件配置**(零代码出生/触发执行能力,替代过去的 E003_YouZhi 专属脚本):
|
||||
- `_abilityId`:`e003_fall`(与 `ABL_E003_Fall.asset` 的 `abilityId` 一致)
|
||||
- `_executeOnSpawn`:勾选 ✓(对象池生成时自动触发下落)
|
||||
- 若是场景预置(非对象池),由场景战斗触发器 / UnityEvent / 动画事件调用本组件的 `Trigger()` 方法激活下落
|
||||
|
||||
**EnemySensorHub**:
|
||||
|
||||
@@ -481,7 +483,7 @@ Selector
|
||||
| `Skill02_End.anim` | 头槌收招(单次) | `RepeatSlamAbility._endClip` |
|
||||
| `Skill03.anim` | 吐酸液(单次) | `ProjectileAttackAbility.attackSequence[0/1].clip` |
|
||||
| `Flip.anim` | 翻身转向(单次) | `FacePlayerAbility._faceClip` |
|
||||
| `Death_Pre.anim` | 死亡前摇(循环,约3秒) | `E004_ZhiMu._deathPreClip` |
|
||||
| `Death_Pre.anim` | 死亡前摇(循环,约3秒) | `EnemyDeathSequence._deathPreClip` |
|
||||
| `Death.anim` | 死亡消散(单次) | AnimConfig.Dead |
|
||||
|
||||
### Step 2:ScriptableObject
|
||||
@@ -503,7 +505,7 @@ Selector
|
||||
|
||||
```
|
||||
ENM_ZhiMu (根节点)
|
||||
├── 组件:E004_ZhiMu(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemyBase、EnemyDeathSequence、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemySensorHub
|
||||
├── 组件:EnemyFeedback、Rigidbody2D
|
||||
├── HurtBox/ → 组件:HurtBox、Collider2D
|
||||
@@ -518,10 +520,11 @@ ENM_ZhiMu (根节点)
|
||||
└── Flip_Ability → 组件:FacePlayerAbility
|
||||
```
|
||||
|
||||
**E004_ZhiMu 组件配置**:
|
||||
**EnemyDeathSequence 组件配置**(零代码死亡前摇无敌演出,替代过去的 E004_ZhiMu 专属 Die() 重写):
|
||||
- `_deathPreClip`:拖入 `Death_Pre.anim`
|
||||
- `_hurtBox`:拖入 `HurtBox/` 组件
|
||||
- `_deathPreDuration`:`3`(与 Death_Pre 动画时长一致,策划调整)
|
||||
- `_duration`:`3`(与 Death_Pre 动画时长一致,策划调整)
|
||||
- `_hurtBoxesToDisable`:拖入 `HurtBox/` 组件(演出期间停用,对象池复用时出生自动恢复)
|
||||
- `_stopBehaviorTree` / `_stopMovement`:默认勾选(演出期间停 BT 与移动)
|
||||
|
||||
**AppearAbility**:
|
||||
- `_config`:`ABL_E004_Appear.asset`
|
||||
@@ -623,7 +626,7 @@ Selector
|
||||
| `Move.anim` | 移动(循环) | AnimConfig.Walk/Run |
|
||||
| `Skill01.anim` | 撕咬(单次) | `MeleeVulnerabilityAbility._attackClip` |
|
||||
| `Skill02.anim` | 吐酸液(单次,连续两轮复用) | `ProjectileAttackAbility.attackSequence[0/1].clip` |
|
||||
| `Death_Pre.anim` | 死亡前摇(含 AnimationEvent) | `E005_FeiZhi._deathPreClip` |
|
||||
| `Death_Pre.anim` | 死亡前摇(含 AnimationEvent) | `EnemyDeathSequence._deathPreClip` |
|
||||
| `Death.anim` | 死亡 | AnimConfig.Dead |
|
||||
|
||||
> ⚠️ **Death_Pre AnimationEvent 设置(关键步骤)**:
|
||||
@@ -647,7 +650,7 @@ Selector
|
||||
|
||||
```
|
||||
ENM_FeiZhi (根节点)
|
||||
├── 组件:E005_FeiZhi(C# 脚本)、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemyBase、EnemyDeathSequence、EnemySpawnerOnEvent、EnemyMovement、EnemyNavAgent、NavAgent、TransformBasedMovement
|
||||
├── 组件:EnemySensorHub
|
||||
├── 组件:Rigidbody2D
|
||||
├── HurtBox/ → 组件:HurtBox
|
||||
@@ -658,12 +661,16 @@ ENM_FeiZhi (根节点)
|
||||
└── Acid_Ability → 组件:ProjectileAttackAbility
|
||||
```
|
||||
|
||||
**E005_FeiZhi 配置**:
|
||||
**EnemyDeathSequence 配置**(零代码死亡前摇无敌演出):
|
||||
- `_deathPreClip`:`Death_Pre.anim`
|
||||
- `_hurtBox`:`HurtBox/` 组件
|
||||
- `_deathPreDuration`:与动画时长一致
|
||||
- `_spawnCount`:`3`(生成 E003 数量,策划调整)
|
||||
- `_spawnRadius`:`1.5`(生成散布半径)
|
||||
- `_duration`:与动画时长一致
|
||||
- `_hurtBoxesToDisable`:`HurtBox/` 组件
|
||||
|
||||
**EnemySpawnerOnEvent 配置**(零代码动画事件池生成,替代过去的 E005_FeiZhi 专属 SpawnProjectile 重写):
|
||||
- `_payloadKey`:`spawn_e003`(与 Death_Pre 动画事件 payload 一致)
|
||||
- `_poolKey`:`ENM_YouZhi`(对象池 key)
|
||||
- `_count`:`3`(生成幼蛭数量,策划调整)
|
||||
- `_radius`:`1.5`(生成散布半径)
|
||||
|
||||
**MeleeVulnerabilityAbility(撕咬)**:
|
||||
- `_config`:`ABL_E005_Bite.asset`
|
||||
@@ -1048,18 +1055,18 @@ Selector [嘲风根节点]
|
||||
**原因 A**:`AnimatedCeilingDropAbility._groundMask` 未设置,导致落地检测失败,能力超时后强制结束。
|
||||
**修复**:将 Ground Layer 加入 `_groundMask`。
|
||||
|
||||
**原因 B**:`E003_YouZhi._activateOnSpawn` 未勾选(对象池路径无法触发下落)。
|
||||
**修复**:在 Inspector 勾选 `_activateOnSpawn`。
|
||||
**原因 B**:`EnemyAbilityTrigger._executeOnSpawn` 未勾选(对象池路径无法触发下落),或 `_abilityId` 与 `ABL_E003_Fall.asset` 的 `abilityId`(`e003_fall`)不一致。
|
||||
**修复**:在 Inspector 勾选 `_executeOnSpawn` 并确认 `_abilityId` 拼写正确。
|
||||
|
||||
---
|
||||
|
||||
### ❌ E005 死亡后没有生成 E003
|
||||
|
||||
**原因 A**:`Death_Pre.anim` 中没有 AnimationEvent,或函数名/参数拼写错误。
|
||||
**修复**:打开动画编辑器,确认 AnimationEvent 的函数为 `SpawnProjectile`,参数为 `"spawn_e003"`(区分大小写)。
|
||||
**修复**:打开动画编辑器,确认 AnimationEvent 的函数为 `SpawnProjectile`,参数为 `"spawn_e003"`(区分大小写),且与 `EnemySpawnerOnEvent._payloadKey` 一致。
|
||||
|
||||
**原因 B**:`ENM_YouZhi` 未注册到 Addressables 或 Pool Key 拼写错误。
|
||||
**修复**:确认 Addressable Address 和对象池 Pool Key 均为 `ENM_YouZhi`(完全一致)。
|
||||
**原因 B**:`EnemySpawnerOnEvent._poolKey` 拼写错误,或 `ENM_YouZhi` 未注册到 Addressables。
|
||||
**修复**:确认 Addressable Address、对象池 Pool Key 与 `EnemySpawnerOnEvent._poolKey` 均为 `ENM_YouZhi`(完全一致)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ Selector
|
||||
├── Sequence [追击]: BD_IsSensorDetecting("aggro") → BD_ChasePlayer
|
||||
└── BD_Patrol
|
||||
```
|
||||
> 预置于天花板的 E003 由场景战斗触发器调用 `E003_YouZhi.ActivateFromCeiling()`;由 E005 死亡生成的走 `OnSpawn()`,均自动触发 `e003_fall`。
|
||||
> 预置于天花板的 E003 由场景战斗触发器调用 `EnemyAbilityTrigger.Trigger()`;由 E005 死亡生成的(对象池路径)经 `_executeOnSpawn` 在出生时自动触发,均执行 `e003_fall` 能力。
|
||||
|
||||
### E004 蛭母(出场→战斗循环:Flip/撕咬/头槌/酸液/靠近)
|
||||
```
|
||||
@@ -120,7 +120,7 @@ Selector
|
||||
### E005 肥蛭(近撕咬+后摇脆弱 / 远酸液 / 追击;死亡生成 E003)
|
||||
```
|
||||
Selector
|
||||
├── Sequence [死亡]: BD_IsStateMatch(Dead) → BD_StopMovement // 死亡生成 E003 由 E005_FeiZhi.SpawnProjectile(AnimationEvent) 处理,不走 BT
|
||||
├── Sequence [死亡]: BD_IsStateMatch(Dead) → BD_StopMovement // 死亡生成 E003 由 EnemySpawnerOnEvent(SpawnProjectile 动画事件路由)处理,不走 BT
|
||||
├── Sequence [撕咬]: BD_CanUseAbility("e005_bite", CheckRange) → BD_UseAbility("e005_bite")
|
||||
├── Sequence [酸液]: BD_CanUseAbility("e005_acid") → BD_UseAbility("e005_acid")
|
||||
└── BD_ChasePlayer
|
||||
|
||||
Reference in New Issue
Block a user