docs(enemy): Boss AI 单轨落地——新增作者指南,清理描述已删除系统的长期文档
新增 Docs/Guides/09_BossAi_Authoring_Guide.md: 定制路径写法([AiDefinition] + AiScript)、建态原语(AiStateFragments + BossFragments + IBossControl)、阶段=换招池、一招怎么配(EnemyAbilitySO + EnemyAttackSO + 动画事件)、开战触发、死亡归物理层, 以已落地的 ChaoFengAi 为逐段范例,附 Boss 专属陷阱与已知缺口。 08 号指南加交叉引用。 删除两份整份描述已删除且从未实现的体系的文档: Docs/Architecture/23_BossSkillModule.md、Docs/Design/47_BossSkillSystem.md。 删前已确认全库无 Markdown 链接残留,索引行与关联文档行改指新指南或 spec。 修订:25_CharacterArchitectureOverview §4 Boss 章节按实际代码重写; 07_EnemyModule 加过时提示、§11 改重定向;02_EventSystem 修正 Boss 事件发送方; 19_BossPatternLibrary 加废止提示(设计意图仍有效,类型名已废); AssetFolderSpec 删旧 Boss 技能编辑器条目;三处 README/索引同步。 Docs_Dev/ 历史记录保留不动。 spec 标记为已实施,并记录实施期偏差(无 Boss 骨架、Telegraph 枚举保留、 阶段直查不走黑板、BossSkillEvent 一并删除)与八项已知未完成项, 其中 EnemyHurtState 无受击动画永久卡死为最高优先级、且与 Boss 轨无关。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,30 @@
|
||||
# 07 · 敌人模块
|
||||
|
||||
> **命名空间** `BaseGames.Enemies`、`BaseGames.Enemies.AI`、`BaseGames.Enemies.Navigation`、`BaseGames.Enemies.Boss.Patterns`
|
||||
> **命名空间** `BaseGames.Enemies`、`BaseGames.Enemies.Abilities`、`BaseGames.Enemies.Navigation`、`BaseGames.AI`
|
||||
> **程序集** 见各 asmdef
|
||||
> **路径** `Assets/Scripts/Enemies/`
|
||||
> **依赖** `BaseGames.Combat`、`Kybernetik.Animancer`、`BehaviorDesigner.Runtime`、`PathBerserker2d`
|
||||
> **路径** `Assets/_Game/Scripts/Enemies/`
|
||||
> **依赖** `BaseGames.Combat`、`Kybernetik.Animancer`
|
||||
|
||||
---
|
||||
|
||||
> ## ⚠️ 本文部分章节已过时(2026-07-30)
|
||||
>
|
||||
> 决策层与 Boss 轨已两度重构,以下章节描述的类型**在代码库中已不存在**,保留仅供追溯历史,
|
||||
> **不要照着它们去找类型或写新代码**:
|
||||
>
|
||||
> | 章节 | 状态 |
|
||||
> |---|---|
|
||||
> | §8 `Behavior Designer 任务类目录` | 第三方行为树插件已移除。决策层现为自研 `BrainGraph`(`AiScript` / `BrainBuilder` / `AiRuntime` / `EnemyAiBrain`) |
|
||||
> | §10 `BossOrchestrator` | 已删除。开战由 `BossFightTrigger` 发 `AiSignal.Engaged`,阶段由 `BossBase.EnterPhase` + `BossPhaseAbilityGate` 承担 |
|
||||
> | §11 `AttackPatternSO 与 TelegraphSystem` | 整节已删除的类型;预警统一改为动画时间轴上的事件 |
|
||||
> | §9 `BossBase` 的字段清单 | 已大幅瘦身:技能执行器、预警系统、弹反反制均已移除;新增 `IBossControl` 实现与阶段门引用 |
|
||||
>
|
||||
> **当前有效的写法**(这两份是权威):
|
||||
> - 小怪:[`Docs/Guides/08_EnemyAi_Authoring_Guide.md`](../Guides/08_EnemyAi_Authoring_Guide.md)
|
||||
> - Boss:[`Docs/Guides/09_BossAi_Authoring_Guide.md`](../Guides/09_BossAi_Authoring_Guide.md)
|
||||
> - 设计依据:`Docs_Dev/superpowers/specs/2026-07-30-boss-ai-single-track-design.md`
|
||||
>
|
||||
> 本文其余章节(`EnemyBase` / `EnemyStats` / `EnemyMovement` / 感知 / 掉落 / 池化等)仍然有效。
|
||||
|
||||
---
|
||||
|
||||
@@ -16,10 +37,10 @@
|
||||
5. [EnemyNavAgent](#5-enemynavagent)
|
||||
6. [EnemyStatsSO](#6-enemystatsso)
|
||||
7. [EnemyAnimationConfigSO](#7-enemyanimationconfigso)
|
||||
8. [Behavior Designer 任务类目录](#8-behavior-designer-任务类目录)
|
||||
9. [BossBase](#9-bossbase)
|
||||
10. [BossOrchestrator](#10-bossorchestrator)
|
||||
11. [AttackPatternSO 与 TelegraphSystem](#11-attackpatternso-与-telegraphsystem)
|
||||
8. ~~[决策层任务类目录](#8-behavior-designer-任务类目录)~~(已过时,见页首提示)
|
||||
9. [BossBase](#9-bossbase)(字段清单已过时)
|
||||
10. ~~[BossOrchestrator](#10-bossorchestrator)~~(已删除)
|
||||
11. ~~[AttackPatternSO 与 TelegraphSystem](#11-attackpatternso-与-telegraphsystem)~~(已删除)
|
||||
12. [DeathShade(死亡遗骸)](#12-deathshade)
|
||||
13. [Enemy Prefab 层级结构](#13-enemy-prefab-层级结构)
|
||||
14. [LootTableSO 与 LootResolver](#14-loottableso-与-lootresolver)
|
||||
@@ -551,147 +572,17 @@ public class BossOrchestrator : MonoBehaviour
|
||||
|
||||
---
|
||||
|
||||
## 11. AttackPatternSO 与 TelegraphSystem
|
||||
## 11. ~~AttackPatternSO 与 TelegraphSystem~~(已删除)
|
||||
|
||||
```csharp
|
||||
// 路径: Assets/Scripts/Enemies/Boss/Patterns/AttackPatternSO.cs
|
||||
[CreateAssetMenu(menuName = "Enemies/Boss/AttackPattern")]
|
||||
public class AttackPatternSO : ScriptableObject
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct AttackEntry
|
||||
{
|
||||
public string AttackId; // BD 任务通过此 ID 触发
|
||||
public float Weight; // 随机权重(模式随机选择)
|
||||
public float Cooldown;
|
||||
public float TelegraphDuration; // 0 = 无预警
|
||||
public string TelegraphVfxKey; // Addressable 键
|
||||
public DamageSourceSO DamageSource;
|
||||
}
|
||||
这两个类型连同整套旧 Boss 技能轨已于 2026-07-30 删除。当前等价物:
|
||||
|
||||
public AttackEntry[] Attacks;
|
||||
public float PhaseSpeedMultiplier = 1f; // 此阶段移速倍率
|
||||
}
|
||||
| 旧类型 | 现在由谁承担 |
|
||||
|---|---|
|
||||
| `AttackPatternSO`(攻击条目 + 权重 + 冷却 + 预警时长) | `EnemyAbilitySO`(id / 冷却 / 权重 / 优先级 / 触发范围 / 中断规则)+ `EnemyAttackSO`(clip + 归一化时机);选招由 `EnemyAttackSelector` 负责 |
|
||||
| `AttackPatternEditor`(命中帧可视化 Inspector) | 暂无替代。能力资产的编辑器总览(`EnemyAbilityModule`)是已记录的待办 |
|
||||
| `TelegraphSystem`(预警 VFX 协程) | 动画时间轴:预警是 clip 的一段,判定 / VFX / 音效 / 无敌帧全部挂动画事件(见 `EnemyAnimationEvents`) |
|
||||
|
||||
// 路径: Assets/Scripts/Enemies/Boss/Patterns/TelegraphSystem.cs
|
||||
// 攻击预警系统:在攻击前若干帧显示视觉提示
|
||||
public class TelegraphSystem : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private ObjectPoolManager _pool;
|
||||
|
||||
// 开始预警(BD_TelegraphAttack 调用)
|
||||
public IEnumerator ShowTelegraph(string vfxKey, float duration, Vector2 position);
|
||||
// 1. 从对象池取出预警 VFX
|
||||
// 2. 等待 duration 秒
|
||||
// 3. 归还 VFX(攻击开始)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 11.1 AttackPatternEditor(命中帧可视化 Inspector)
|
||||
|
||||
> **路径**:`Assets/Editor/Enemies/AttackPatternEditor.cs`
|
||||
> **目标用户**:Boss 战斗设计师(配置攻击权重、预警时长、伤害数值时,无需对照原始 Inspector 多层嵌套)
|
||||
|
||||
```csharp
|
||||
[CustomEditor(typeof(AttackPatternSO))]
|
||||
public class AttackPatternEditor : UnityEditor.Editor
|
||||
{
|
||||
// ── 折叠状态 ─────────────────────────────────────────────────────
|
||||
private bool[] _foldouts;
|
||||
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
var so = (AttackPatternSO)target;
|
||||
var prop = serializedObject;
|
||||
prop.Update();
|
||||
|
||||
// ── 整体参数 ─────────────────────────────────────────────────
|
||||
EditorGUILayout.PropertyField(prop.FindProperty("PhaseSpeedMultiplier"));
|
||||
EditorGUILayout.Space(6);
|
||||
|
||||
// ── 攻击条目列表(可视化条形图 + 折叠面板) ─────────────────
|
||||
EditorGUILayout.LabelField("AttackEntries", EditorStyles.boldLabel);
|
||||
var attacks = so.Attacks;
|
||||
if (attacks == null || attacks.Length == 0)
|
||||
{
|
||||
EditorGUILayout.HelpBox("尚无攻击条目。", MessageType.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_foldouts == null || _foldouts.Length != attacks.Length)
|
||||
_foldouts = new bool[attacks.Length];
|
||||
|
||||
float totalWeight = 0f;
|
||||
foreach (var a in attacks) totalWeight += Mathf.Max(a.Weight, 0.001f);
|
||||
|
||||
for (int i = 0; i < attacks.Length; i++)
|
||||
{
|
||||
var entry = attacks[i];
|
||||
float ratio = entry.Weight / totalWeight;
|
||||
|
||||
// 折叠标题行:「[Bar████░░] AttackId 权重%」
|
||||
EditorGUILayout.BeginHorizontal();
|
||||
var barRect = GUILayoutUtility.GetRect(0, 16, GUILayout.Width(80));
|
||||
EditorGUI.DrawRect(barRect, new Color(0.2f, 0.4f, 0.8f, 0.3f));
|
||||
EditorGUI.DrawRect(new Rect(barRect.x, barRect.y, barRect.width * ratio, barRect.height),
|
||||
new Color(0.2f, 0.6f, 1f, 0.8f));
|
||||
|
||||
_foldouts[i] = EditorGUILayout.Foldout(_foldouts[i],
|
||||
$" {entry.AttackId} ({ratio:P0})", true);
|
||||
EditorGUILayout.EndHorizontal();
|
||||
|
||||
if (_foldouts[i])
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
var arrayProp = prop.FindProperty("Attacks").GetArrayElementAtIndex(i);
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("AttackId"));
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("Weight"));
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("Cooldown"));
|
||||
|
||||
// 预警时长:0 = 无预警(灰色提示)
|
||||
float tele = entry.TelegraphDuration;
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("TelegraphDuration"));
|
||||
if (tele <= 0f)
|
||||
EditorGUILayout.HelpBox("TelegraphDuration = 0:此攻击无预警(即时)", MessageType.None);
|
||||
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("TelegraphVfxKey"));
|
||||
EditorGUILayout.PropertyField(arrayProp.FindPropertyRelative("DamageSource"));
|
||||
|
||||
// 快速展示 DamageSource 摘要(避免策划必须展开嵌套 SO)
|
||||
if (entry.DamageSource != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUILayout.LabelField(
|
||||
$"伤害预览: {entry.DamageSource.BaseDamage} × {entry.DamageSource.DamageMultiplier:F1} " +
|
||||
$"= {Mathf.RoundToInt(entry.DamageSource.BaseDamage * entry.DamageSource.DamageMultiplier)} [{entry.DamageSource.Type}]",
|
||||
EditorStyles.miniLabel);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
|
||||
// 一键 Ping 关联 SO
|
||||
if (entry.DamageSource != null && GUILayout.Button("Ping DamageSourceSO", GUILayout.Height(18)))
|
||||
EditorGUIUtility.PingObject(entry.DamageSource);
|
||||
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prop.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**提供能力一览**:
|
||||
|
||||
| 功能 | 收益 |
|
||||
|------|------|
|
||||
| 随机权重百分比 + 条形图 | 策划直观感受攻击频率分布 |
|
||||
| TelegraphDuration=0 警告 | 防止无意做成即时攻击 |
|
||||
| DamageSource 内联摘要 | 查看伤害值无需展开嵌套 SO |
|
||||
| Ping 关联 SO 按钮 | 快速定位引用资产 |
|
||||
配招写法见 [`Docs/Guides/09_BossAi_Authoring_Guide.md`](../Guides/09_BossAi_Authoring_Guide.md) §4。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user