docs(enemy): Boss AI 双轨统一实施计划——21 个任务,分两阶段
阶段一 Task 1-15 只加不删(每 Task 编译通过、测试全绿,末尾嘲风能用新轨打起来); 阶段二 Task 16-21 删旧轨(先改引用方,再删被引用类型;先删资产,再删脚本)。 编写期核查坐实并更正 spec 两处: - 取消 EnemyBase.SetInvincible(float):HurtBox.SetInvincible(bool) 已存在, 玩家侧 EnableIFrame/DisableIFrame 就走它,无敌时长由动画上两事件间距表达。 新增件由六件减为五件。 - 竞技场锚点改挂 IBossControl,不走黑板:EnemyAiBrain._context 是私有字段 且无公开访问器(BossBase 无从写入),且 ResetScratch 会清黑板带来隐式时序约束。 另确认 EditorScaffoldUtils.CreateSOAsset(Type,...) 重载已存在,无需新增辅助。
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -193,16 +193,21 @@ public sealed class ChaoFengAi : AiScript
|
||||
|
||||
---
|
||||
|
||||
## 5. 新增的六件
|
||||
## 5. 新增的五件
|
||||
|
||||
| # | 内容 | 规模 |
|
||||
|---|---|---|
|
||||
| 1 | `IBossControl` facet + `IAiContext.Boss` | 小接口 |
|
||||
| 2 | `BossPhaseAbilityGate` 组件 | 小组件 |
|
||||
| 3 | `AttackSelectionMode.WeightedRandomAntiRepeat` + 选招器防重复 | 改两个文件 |
|
||||
| 4 | `EnemyAnimationEvents` 补 4 个 case | 各 2–3 行 |
|
||||
| 5 | `EnemyBase.SetInvincible(float)` | 约 6 行 |
|
||||
| 6 | `BossArenaAnchors` 组件 + 「移动到第 N 锚点」图片段 | 小组件 |
|
||||
| 4 | `EnemyAnimationEvents` 补 4 个 case + 两个子系统引用字段 | 各 2–3 行 |
|
||||
| 5 | `BossArenaAnchors` 组件 + 「移动到第 N 锚点」图片段 | 小组件 |
|
||||
|
||||
> 修订(2026-07-30,实施计划阶段):初稿列的第 5 件「`EnemyBase.SetInvincible(float)`」**已取消**。
|
||||
> 核查 `PlayerAnimationEvents` 后确认玩家侧的 `EnableIFrame` / `DisableIFrame` 走的是
|
||||
> `HurtBox.SetInvincible(bool)`——该 API **已存在**,无敌时长由动画时间轴上两个事件的间距表达。
|
||||
> 敌人侧照同一形态接线即可,不需要在 `EnemyBase` 上新造带时长的无敌源。
|
||||
> 这也更正确:时长归动画,不归代码常量。
|
||||
|
||||
### 5.1 `IBossControl`
|
||||
|
||||
@@ -216,10 +221,24 @@ namespace BaseGames.AI
|
||||
bool IsPhaseTransitioning { get; }
|
||||
bool ResourceFull { get; } // BossResource 满值;无资源组件时恒 false
|
||||
void BeginPhaseTransition(int targetPhase, float invincibleDuration);
|
||||
|
||||
// 竞技场锚点(§5.5)。归本 facet 而非黑板:见下方修订说明。
|
||||
Vector2 AnchorAt(int index);
|
||||
float DistanceToAnchor(int index);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 修订(2026-07-30,实施计划阶段):锚点坐标初稿设计为经 `IAiContext.Blackboard` 传递
|
||||
> (`BossBase` 在 `Awake` 写入黑板键)。该方案有两处硬阻塞,已废弃:
|
||||
> 1. **拿不到黑板** —— `EnemyAiBrain._context` 是私有字段且无公开访问器,`BossBase` 无从写入。
|
||||
> 2. **时序坑** —— `EnemyBrainContext.ResetScratch()` 会 `_blackboard.Clear()`(对象池复用时调用),
|
||||
> 写入点必须排在它之后,是个易错的隐式顺序依赖。
|
||||
>
|
||||
> 改为挂在 `IBossControl` 上:锚点本就是 Boss 专属知识,facet 已存在,`BossBase` 在 `Awake`
|
||||
> 解析组件即可。净收益是少一个失败模式(黑板键缺失)、少一条隐式时序约束,且
|
||||
> `DistanceToAnchor` 把"我离锚点多远"封在 Boss 内部,不需要给 AI 层引入新的位置概念。
|
||||
|
||||
`EnemyBrainContext.Boss => _boss ?? throw new InvalidOperationException(...)`。
|
||||
按 CLAUDE.md 第 6 条:小怪图误用它必须崩,不能返回一个空对象把问题盖住。
|
||||
|
||||
@@ -261,8 +280,11 @@ C# 单继承直接堵死。
|
||||
| `PlaySFX` / `TriggerFeedback` | **音效预警**——竞品有 Boss 用两句语音区分物理招与远程招,预警的是招式**类别**而非具体招式,让玩家缩小可能性但不能确定。这是最经济的 telegraph 手法,现在写不出来 |
|
||||
| `EnableIFrame` / `DisableIFrame` | 招式中途无敌:突进穿过玩家时不吃伤害、传送消失期间无敌 |
|
||||
|
||||
配套 §5 第 5 项:`EnemyBase.IsInvincible` 是只读计算属性(`Dead || _deathSequenceActive`),
|
||||
没有带时长的无敌源,需新增 `SetInvincible(float)` 并纳入 `IsInvincible`。
|
||||
四个 case 的实现与 `PlayerAnimationEvents` 逐字对称:反馈两件走 `IFeedbackPlayer.TriggerPreset` /
|
||||
`PlaySFXById`(`EnemyFeedback` 已实现该接口),无敌两件走 `HurtBox.SetInvincible(bool)`(API 已存在)。
|
||||
`EnemyAnimationEvents` 因此需补两个子系统引用:`HurtBox _hurtBox` 与 `IFeedbackPlayer _feedback`
|
||||
(后者在 `Awake` 用 `GetComponentInParent<IFeedbackPlayer>() ?? NullFeedbackPlayer.Instance` 解析,
|
||||
与玩家侧同写法)。
|
||||
|
||||
### 5.5 `BossArenaAnchors`
|
||||
|
||||
@@ -270,6 +292,10 @@ C# 单继承直接堵死。
|
||||
`IEnemyLocomotion.MoveTo(Vector2)` 能到点,但锚点集合无处安放。
|
||||
一个持有 `Transform[]` 的组件 + 一个「移动到第 N 个锚点」的图片段即可。
|
||||
|
||||
坐标经 `IBossControl.AnchorAt(int)` / `DistanceToAnchor(int)` 暴露给图(不走黑板,见 §5.1 修订)。
|
||||
锚点物体放在场景里而非 SO 里——它随房间布局走。下标越界或引用为空**显式抛**,
|
||||
不回退到 Boss 自身位置(那会让"锚点漏配"表现为"Boss 站着不动",是典型的下游兜底掩盖问题)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 退役清单
|
||||
@@ -469,8 +495,8 @@ C# 单继承直接堵死。
|
||||
改 Assets/_Game/Scripts/Enemies/Abilities/EnemyAbilityBase.cs CanUse += enabled;删 TelegraphRoutine
|
||||
改 Assets/_Game/Scripts/Enemies/Abilities/EnemyAbilitySO.cs + designNote;− telegraph 两字段;fileName → ABL_
|
||||
改 Assets/_Game/Scripts/Enemies/AIBrain/Modules/Engagement/ApproachAttackEngagement.cs 建态逻辑提静态
|
||||
改 Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs + 4 个 case
|
||||
改 Assets/_Game/Scripts/Enemies/EnemyBase.cs + SetInvincible;改名 NotifyDecisionStop;− ConsumeParryEvent
|
||||
改 Assets/_Game/Scripts/Animation/EnemyAnimationEvents.cs + 4 个 case;+ _hurtBox / _feedback 引用
|
||||
改 Assets/_Game/Scripts/Enemies/EnemyBase.cs 改名 NotifyDecisionStop;− ConsumeParryEvent
|
||||
改 Assets/_Game/Scripts/Enemies/Behaviors/EnemyDeathSequence.cs 调用点改名
|
||||
改 Assets/_Game/Scripts/Combat/HurtBox.cs + 伤害倍率
|
||||
改 Assets/_Game/Scripts/Enemies/Boss/BossBase.cs 瘦身约 150 行;实现 IBossControl
|
||||
|
||||
Reference in New Issue
Block a user