Files
zeling_v2/Docs/Design/47_BossSkillSystem.md
2026-05-08 11:04:00 +08:00

876 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 47 · Boss 技能系统框架Boss Skill System Framework
> **命名空间** `BaseGames.Enemies.Boss.Skills`
> **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md)
> **依赖文档**
> - [04_CombatSystem](./04_CombatSystem.md) — `DamageInfo` / `HitBox` / `HurtBox` 底层
> - [19_BossPatternLibrary](./19_BossPatternLibrary.md) — `AttackPatternSO` / `BossOrchestrator` / 阶段系统
> - [21_SpellSystem](./21_SpellSystem.md) — `FormSkillSO` / 玩家技能(反制参照)
> - [05_ParrySystem](./05_ParrySystem.md) — 弹反流水线
> - [54_PoiseSystem](./54_PoiseSystem.md) — 霸体 / 打断等级(`PoiseWindowConfig` / `BreakLevel`
---
## 目录
1. [系统定位与层次关系](#1-系统定位与层次关系)
2. [BossSkillSO — 技能数据层](#2-bossskillso--技能数据层)
3. [Boss 技能分类体系](#3-boss-技能分类体系)
4. [弱点与脆弱窗口系统](#4-弱点与脆弱窗口系统)
5. [玩家反制接口](#5-玩家反制接口)
6. [Boss 技能序列系统](#6-boss-技能序列系统)
7. [Boss 资源系统(愤怒 / 状态充能)](#7-boss-资源系统愤怒--状态充能)
8. [场景联动接口](#8-场景联动接口)
9. [平衡数据模板](#9-平衡数据模板)
10. [编辑器工作流](#10-编辑器工作流)
11. [事件频道扩展](#11-事件频道扩展)
12. [资产路径规范](#12-资产路径规范)
---
## 1. 系统定位与层次关系
### 1.1 为什么需要 BossSkillSystem
`19_BossPatternLibrary``AttackPatternSO` 描述**单次攻击动作**(前摇/活跃帧/后摇/弹射物),
`BossSkillSystem` 在其上管理**更高阶的技能语义**
| 关注点 | AttackPatternSO | BossSkillSO |
|--------|----------------|-------------|
| 粒度 | 单个动作片段 | 一个完整技能(可包含多段动作)|
| 核心数据 | 时序 / 伤害 / 弹射物 | 分类 / 反制接口 / 脆弱窗口 / 序列编排 |
| 执行者 | `BossOrchestrator` | `BossSkillExecutor`(包装 Orchestrator|
| 平衡视角 | 单次伤害值 | 技能风险/收益比、战斗节奏 |
### 1.2 层次关系图
```
┌─────────────────────────────────────────────────────────┐
│ Boss 战斗管线 │
│ │
│ BossSkillSO ──────────────────────────────────────┐ │
│ │ 技能语义 / 分类 / 反制接口 / 脆弱窗口 │ │
│ ▼ │ │
│ SkillSequenceSO (可选) │ │
│ │ 多步骤序列(前置技 → 触发技) │ │
│ ▼ │ │
│ AttackPatternSO ←── 19_BossPatternLibrary │ │
│ │ 单动作:时序 / 弹射物 / 预警 / 权重 │ │
│ ▼ │ │
│ BossOrchestrator ←── 19_BossPatternLibrary │ │
│ │ 运行时选择 → 执行 │ │
│ ▼ │ │
│ HitBox / DamageInfo ←── 04_CombatSystem │ │
│ │ │
│ ◄──── WeakPointSystem (脆弱窗口) ─────────────────┘ │
│ ◄──── PlayerInteractionContract (玩家反制接口) │
│ ◄──── ArenaIntegration (场景联动) │
└─────────────────────────────────────────────────────────┘
```
### 1.3 设计原则
1. **分类先于设计** — 每个 Boss 技能必须在开发前确定其 `BossSkillType``InteractionTag`
2. **反制可读性** — 每个技能必须明确"玩家用什么技能/动作可以反制/利用"
3. **脆弱窗口强制存在** — 每个技能至少有一个 `VulnerabilityWindow`(后摇 ≥ 0.5s 或专属弱点)
4. **不与 AttackPatternSO 重复** — 伤害数值/时序数据保留在 AttackPatternSO不在 BossSkillSO 中重复
---
## 2. BossSkillSO — 技能数据层
```csharp
[CreateAssetMenu(menuName = "Enemies/Boss/BossSkill")]
public class BossSkillSO : ScriptableObject
{
// ─────────────────────────────
// 1. 基础信息(策划填写)
// ─────────────────────────────
[Header("基础信息")]
public string skillId; // 唯一 ID格式: {BossId}_{SkillName}
public string displayName; // 设计阶段展示名(不用于玩家 UI
[TextArea(1, 4)]
public string designNote; // 设计意图(该技能考察玩家什么能力)
// ─────────────────────────────
// 2. 分类标签
// ─────────────────────────────
[Header("分类")]
public BossSkillCategory category; // 主分类(见 §3
public InteractionTag[] tags; // 可多选(见 §3.2
public PhaseAvailability phaseAvail; // 在哪些阶段可用
// ─────────────────────────────
// 3. 核心攻击动作引用
// ─────────────────────────────
[Header("攻击动作")]
[Tooltip("构成此技能的 AttackPatternSO 序列(单个技能 = 数组长度 1连击/多段 = 多个)")]
public AttackPatternSO[] attackPatterns; // 按执行顺序排列
// ─────────────────────────────
// 4. 脆弱窗口(见 §4
// ─────────────────────────────
[Header("脆弱窗口")]
public VulnerabilityWindowConfig vulnerabilityWindow;
// ─────────────────────────────
// 5. 玩家反制接口(见 §5
// ─────────────────────────────
[Header("玩家反制接口")]
public PlayerCounterResponse[] counterResponses; // 被不同玩家技能反制时的反应
// ─────────────────────────────
// 6. 场景联动(见 §8
// ─────────────────────────────
[Header("场景联动")]
public ArenaEventTrigger[] arenaEvents; // 此技能触发的场景事件
// ─────────────────────────────
// 7. 资源消耗Boss 资源系统)
// ─────────────────────────────
[Header("Boss 资源")]
public BossResourceCost resourceCost; // 使用此技能消耗的 Boss 自身资源(见 §7
public bool buildsRage; // 使用后是否积累愤怒值
// ─────────────────────────────
// 8. 霸体配置(新增)
// ─────────────────────────────
[Header("霸体配置")]
[Tooltip("此技能执行期间的霸体窗口None = 可被玩家攻击打断),见 54_PoiseSystem §8")]
public PoiseWindowConfig poiseWindow; // 见 54_PoiseSystem §8
}
```
---
## 3. Boss 技能分类体系
### 3.1 主分类BossSkillCategory
```csharp
public enum BossSkillCategory
{
// ── 主动攻击 ──
Melee, // 近战物理攻击(覆盖正前方/扇形/冲刺)
Ranged, // 远程弹射物攻击
Charge, // 冲刺突进类
AoE, // 全场/大范围爆炸类
Environmental, // 激活/改变场景(召唤陷阱/破坏平台/生成危险区域)
Summon, // 召唤小怪/分身/辅助体
// ── 特殊状态 ──
Buff, // Boss 自身增益(加速/护甲/无敌)
Debuff, // 对玩家施加负面状态(减速/沉默/中毒/禁锢)
Phase, // 阶段转换技(仅在 HP 阈值触发,不参与随机选择)
// ── 被动 ──
Passive, // 持续生效的被动机制(不通过 BossOrchestrator 选取)
Reactive, // 响应玩家行为的反应技(玩家使用技能 → Boss 反制)
}
```
### 3.2 交互标签InteractionTag
可多选的属性标记,用于确定技能与玩家系统的交互方式:
```csharp
[Flags]
public enum InteractionTag
{
None = 0,
Parryable = 1 << 0, // 可弹反(连接 ParrySystem
PerfectParryOnly = 1 << 1, // 仅完美弹反有效
DodgeWindow = 1 << 2, // 有明确的冲刺规避窗口
Unblockable = 1 << 3, // 无法弹反 / 无法格挡
CanBeReflected = 1 << 4, // 弹射物可被反弹回来
ExposesWeakPoint = 1 << 5, // 使用后暴露弱点(触发 VulnerabilityWindow
GrantsPlayerReso = 1 << 6, // 弹反/反制成功后为玩家提供资源(灵力/魄元)
ArenaHazard = 1 << 7, // 改变 Arena 状态(持续危险)
PhaseGate = 1 << 8, // 阶段转换技(不可被打断)
}
```
### 3.3 风险/收益分级
每个技能在设计阶段应确定其**威胁等级**与**反制收益**
| 等级 | 威胁(对玩家的压力)| 反制收益(成功反制的奖励)| 典型形态 |
|------|-----------------|------------------------|---------|
| Low | 低伤 / 可轻松规避 | 小量灵力 | 普通近战、单发弹射物 |
| Mid | 中伤 / 需要主动应对 | 中量灵力 + 脆弱窗口 | 连击、冲刺 |
| High | 高伤 / 必须精准反制 | 大量灵力 + 长脆弱窗口 | 超级技、召唤 |
| Lethal | 极高伤 / 全场 AoE | 击杀后阶段转换 / 大量灵力 | 阶段转换技 |
```csharp
public enum SkillThreatLevel { Low, Mid, High, Lethal }
public enum CounterRewardLevel { None, Small, Medium, Large, Phase }
// 两者都作为 BossSkillSO 的设计标注字段(不参与运行时逻辑)
```
---
## 4. 弱点与脆弱窗口系统
### 4.1 VulnerabilityWindowConfig
定义 Boss 在执行技能**后**何时、何处、如何暴露弱点:
```csharp
[Serializable]
public struct VulnerabilityWindowConfig
{
[Header("触发条件")]
public VulnTriggerType triggerType; // 何时触发(见下方枚举)
public float triggerDelay; // 从触发条件满足到窗口开启的延迟(秒)
[Header("持续时间")]
public float duration; // 脆弱窗口持续时长(秒)
[Header("弱点类型")]
public WeakPointType weakPointType; // 弱点位置/类型
public float damageMultiplier;// 弱点期间受到伤害的倍率(默认 1.5
public bool forceStagger; // 是否强制使 Boss 进入硬直动画
public float staggerDuration; // 强制硬直时长(秒)
[Header("视觉反馈")]
public FeedbackPresetSO openFeedback; // 窗口开启时的 VFX/SFX
public FeedbackPresetSO closeFeedback; // 窗口关闭时的 VFX/SFX
public Color highlightColor; // 弱点高亮颜色(材质颜色叠加)
}
public enum VulnTriggerType
{
OnAttackRecovery, // 攻击后摇阶段自动触发(最常用)
OnParriedSuccess, // 被成功弹反后触发
OnCounterSkillHit, // 被特定玩家技能命中后触发
OnPhaseTransition, // 阶段转换动画期间触发
OnHazardBackfire, // 自己的场景危险伤到自己后触发
OnSummonDefeated, // 召唤物被击败后触发
Manual, // 由 Animator / Timeline 手动触发
}
public enum WeakPointType
{
FullBody, // 全身都是弱点
HeadOnly, // 仅头部
BackOnly, // 仅背部(需要玩家绕后)
CoreExposed, // 核心部位暴露(通常在特定动画帧)
CustomPoint, // 自定义坐标(用 Transform 引用)
}
```
### 4.2 BossWeakPointTracker运行时组件
```csharp
namespace BaseGames.Enemies.Boss.Skills
{
/// <summary>
/// 挂载于 BossBase追踪并管理当前活跃的脆弱窗口。
/// 由 BossSkillExecutor 在技能执行过程中驱动。
/// </summary>
public class BossWeakPointTracker : MonoBehaviour
{
[SerializeField] VoidEventChannelSO _onVulnerabilityOpened;
[SerializeField] VoidEventChannelSO _onVulnerabilityClosed;
bool _isVulnerable;
float _damageMultiplierOverride = 1f;
WeakPointType _activeWeakPoint;
Coroutine _windowCoroutine;
public bool IsVulnerable => _isVulnerable;
public float DamageMultiplierOverride => _damageMultiplierOverride;
public void OpenWindow(VulnerabilityWindowConfig cfg)
{
if (_windowCoroutine != null) StopCoroutine(_windowCoroutine);
_windowCoroutine = StartCoroutine(RunWindow(cfg));
}
public void ForceCloseWindow()
{
if (_windowCoroutine != null) StopCoroutine(_windowCoroutine);
CloseWindow();
}
// ── HurtBox 伤害修正 Hook ──
// 当 BossHurtBox.ReceiveDamage 被调用时,检查 IsVulnerable
// 并将 DamageInfo 的 FinalDamage 乘以 DamageMultiplierOverride
// 此修正在 HurtBox 层完成BossSkillSystem 无需感知具体伤害计算
IEnumerator RunWindow(VulnerabilityWindowConfig cfg)
{
yield return new WaitForSeconds(cfg.triggerDelay);
_isVulnerable = true;
_damageMultiplierOverride = cfg.damageMultiplier;
_activeWeakPoint = cfg.weakPointType;
cfg.openFeedback?.Play(transform.position);
_onVulnerabilityOpened.Raise();
yield return new WaitForSeconds(cfg.duration);
CloseWindow();
cfg.closeFeedback?.Play(transform.position);
}
void CloseWindow()
{
_isVulnerable = false;
_damageMultiplierOverride = 1f;
_onVulnerabilityClosed.Raise();
}
}
}
```
---
## 5. 玩家反制接口
### 5.1 设计意图
每个 Boss 技能必须声明**玩家可用哪些动作/技能来反制它**,以及**反制成功后发生什么**。
这保证了:策划在设计技能时同时设计反制路径;代码层提供一致的反制响应框架。
### 5.2 PlayerCounterResponse
```csharp
[Serializable]
public struct PlayerCounterResponse
{
[Header("反制条件")]
public CounterType counterType; // 玩家用什么触发反制
public string requiredSkillId; // counterType = SpecificSkill 时填写技能 ID
[Header("反制效果(对 Boss")]
public float bossStaggerDuration; // 强制硬直时长0 = 不强制硬直)
public float bossDamageBonus; // 对 Boss 的额外伤害倍率0 = 不额外加)
public bool openVulnWindow; // 是否触发 VulnerabilityWindow
public bool interruptSkill; // 是否打断 Boss 当前技能
[Header("反制收益(对玩家)")]
public int soulPowerGrant; // 给予玩家的灵力数量
public int spiritPowerGrant; // 给予玩家的魄元数量
public FeedbackPresetSO counterFeedback; // 成功反制的特效/音效反馈
}
public enum CounterType
{
Parry, // 弹反成功
PerfectParry, // 完美弹反
DodgeThrough, // 冲刺穿越攻击(无敌帧通过)
SpecificSkill, // 使用特定技能(填 requiredSkillId
WeakPointHit, // 命中暴露的弱点
HazardBackfire, // 利用场景危险伤到 Boss
SummonKill, // 击败召唤物
}
```
### 5.3 反制接口的运行时处理
```csharp
// BossSkillExecutor 在技能生命周期内注册/注销反制监听
public class BossSkillExecutor : MonoBehaviour
{
// 在 StartPattern 时调用:
void RegisterCounters(BossSkillSO skill)
{
foreach (var resp in skill.counterResponses)
{
CounterEventBus.Subscribe(resp.counterType, resp.requiredSkillId,
() => ApplyCounterResponse(resp));
}
}
// 在 EndPattern 时调用:
void UnregisterCounters(BossSkillSO skill) { /* 同步注销 */ }
void ApplyCounterResponse(PlayerCounterResponse resp)
{
if (resp.interruptSkill) _orchestrator.AbortCurrentPattern();
if (resp.bossStaggerDuration > 0) ApplyStagger(resp.bossStaggerDuration);
if (resp.openVulnWindow) _weakPointTracker.OpenWindow(/* 从技能配置取 */);
if (resp.soulPowerGrant > 0) _onGrantPlayerSoulPower.Raise(resp.soulPowerGrant);
if (resp.spiritPowerGrant > 0)_onGrantPlayerSpiritPower.Raise(resp.spiritPowerGrant);
resp.counterFeedback?.Play(transform.position);
}
}
```
---
## 6. Boss 技能序列系统
### 6.1 序列的定义
"技能序列"指一组技能按**条件/状态**依次执行,形成更复杂的战术模式:
- **线性序列**:技能 A → 等待 → 技能 B连招/二段技)
- **分支序列**:技能 A → 判断玩家位置 → 技能 B 或技能 C
- **条件序列**:技能 A 成功命中 → 追加技能 B否则取消
### 6.2 SkillSequenceSO
```csharp
[CreateAssetMenu(menuName = "Enemies/Boss/SkillSequence")]
public class SkillSequenceSO : ScriptableObject
{
public string sequenceId;
public SequenceNode[] nodes; // 序列中的节点列表(按执行顺序)
}
[Serializable]
public class SequenceNode
{
[Header("节点信息")]
public string nodeId;
public SequenceNodeType nodeType;
// ── SkillNode 类型 ──
public BossSkillSO skill; // 要执行的技能
// ── WaitNode 类型 ──
public float waitDuration; // 等待时长(秒)
// ── BranchNode 类型 ──
public SequenceBranchCondition branchCondition;
public string trueNodeId; // 条件为真时跳转到的节点 ID
public string falseNodeId; // 条件为假时跳转到的节点 ID
// ── AbortCondition所有节点通用──
[Tooltip("满足此条件时提前终止序列")]
public SequenceAbortCondition abortCondition;
}
public enum SequenceNodeType
{
SkillNode, // 执行一个 BossSkillSO
WaitNode, // 等待固定时间
BranchNode, // 条件分支
ArenaEventNode,// 触发场景事件(不执行攻击)
}
[Serializable]
public struct SequenceBranchCondition
{
public BranchConditionType type;
[Range(0f,1f)] public float hpThreshold; // HPBelow 时使用
public float range; // InRange 时使用
}
public enum BranchConditionType
{
PlayerInRange,
PlayerAbove,
HPBelow,
LastSkillParried, // 上一个技能被弹反
LastSkillHit, // 上一个技能命中了玩家
}
```
### 6.3 BossSequenceRunner
```csharp
/// <summary>
/// 运行 SkillSequenceSO 的协程控制器,挂载于 BossBase。
/// 由 BehaviorDesigner 的 Action Task RunBossSequence 调用。
/// </summary>
public class BossSequenceRunner : MonoBehaviour
{
public bool IsRunning { get; private set; }
public void RunSequence(SkillSequenceSO sequence, Transform player,
System.Action onComplete = null)
{
if (IsRunning) return;
StartCoroutine(ExecuteSequence(sequence, player, onComplete));
}
public void AbortSequence() { StopAllCoroutines(); IsRunning = false; }
IEnumerator ExecuteSequence(SkillSequenceSO seq, Transform player,
System.Action onComplete)
{
IsRunning = true;
var nodeMap = seq.nodes.ToDictionary(n => n.nodeId);
var node = seq.nodes[0]; // 从第一个节点开始
while (node != null)
{
// 检查提前终止
if (CheckAbort(node.abortCondition)) break;
switch (node.nodeType)
{
case SequenceNodeType.SkillNode:
yield return ExecuteSkillNode(node.skill, player);
node = GetNextNode(nodeMap, node, isSequential: true);
break;
case SequenceNodeType.WaitNode:
yield return new WaitForSeconds(node.waitDuration);
node = GetNextNode(nodeMap, node, isSequential: true);
break;
case SequenceNodeType.BranchNode:
bool cond = EvaluateBranch(node.branchCondition, player);
string nextId = cond ? node.trueNodeId : node.falseNodeId;
node = string.IsNullOrEmpty(nextId) ? null : nodeMap.GetValueOrDefault(nextId);
break;
case SequenceNodeType.ArenaEventNode:
TriggerArenaEvent(node);
node = GetNextNode(nodeMap, node, isSequential: true);
break;
}
}
IsRunning = false;
onComplete?.Invoke();
}
// ... 内部辅助方法省略(由具体 Boss 实现扩展)
}
```
---
## 7. Boss 资源系统(愤怒 / 状态充能)
### 7.1 设计意图
部分 Boss 需要"积累状态"才能释放最强技能,或受到一定伤害后进入特殊形态。
`BossResourceSystem` 提供一个轻量级、可配置的通用资源层,不强制每个 Boss 都使用。
### 7.2 BossResourceConfigSO
```csharp
[CreateAssetMenu(menuName = "Enemies/Boss/ResourceConfig")]
public class BossResourceConfigSO : ScriptableObject
{
public string resourceId; // 如 "Rage" / "PhaseCharge"
public string displayName;
public float maxValue;
public float startValue; // 初始值(通常 0
[Header("自动变化")]
public float passiveRate; // 每秒自动变化量(正=增长/负=衰减0=不自动)
public float onTakeDamageGain; // 每受到 1 点伤害积累量
public float onSkillUseGain; // 每使用一次技能积累量
[Header("满值效果")]
public bool autoTriggerOnFull; // 是否满值时自动触发效果
public BossSkillSO fullTriggerSkill; // 触发的技能
public float resetValueAfterTrigger; // 触发后重置到的值
}
public struct BossResourceCost
{
public string resourceId; // 对应 BossResourceConfigSO.resourceId
public float cost; // 消耗量0 = 不消耗资源)
public float minRequired;// 使用此技能的最低资源要求
}
```
### 7.3 BossResourceTracker运行时
```csharp
public class BossResourceTracker : MonoBehaviour
{
BossResourceConfigSO _config;
float _current;
public float Current => _current;
public float Ratio => _current / _config.maxValue;
public bool IsFull => _current >= _config.maxValue;
public void Gain(float amount)
{
_current = Mathf.Clamp(_current + amount, 0, _config.maxValue);
if (IsFull && _config.autoTriggerOnFull) TriggerFullEffect();
}
public bool TryConsume(BossResourceCost cost)
{
if (cost.resourceId != _config.resourceId) return true; // 不相关资源直接通过
if (_current < cost.minRequired) return false;
_current -= cost.cost;
return true;
}
}
```
---
## 8. 场景联动接口
### 8.1 设计意图
Boss 技能可以**触发场景变化**(破坏平台、激活陷阱、改变重力等),这些变化通过接口解耦,不在 BossSkillSO 中硬编码场景引用。
### 8.2 IArenaInteractable
```csharp
/// <summary>
/// 场景中可被 Boss 技能交互的对象实现此接口。
/// 无需引用 BossBoss 通过 ArenaEventBus 广播,场景监听并响应。
/// </summary>
public interface IArenaInteractable
{
string ArenaObjectId { get; } // 唯一标识(在 BossSkillSO.arenaEvents 中引用)
void OnBossArenaEvent(ArenaEventData data);
}
```
### 8.3 ArenaEventTrigger & ArenaEventData
```csharp
[Serializable]
public struct ArenaEventTrigger
{
public string targetArenaObjectId; // 要影响的场景物件 ID空 = 广播给所有)
public ArenaEventType eventType;
public float delay; // 从技能触发到场景事件的延迟(秒)
public ArenaEventParams parameters;
}
public enum ArenaEventType
{
DestroyPlatform, // 破坏指定平台
ActivateHazard, // 激活陷阱(如喷火管)
DeactivateHazard, // 关闭陷阱
SpawnHazardArea, // 生成持续危险区域(熔岩/毒液水坑)
ShakeArena, // 场景震动
ToggleLighting, // 切换场景光照Boss 技能令场景变暗等)
SpawnPlatform, // 生成新平台(阶段 2 变化)
TriggerCutscene, // 触发小型过场(无需外部管理)
}
[Serializable]
public struct ArenaEventParams
{
public float duration; // 效果持续时间0 = 永久或由物件自行管理)
public float intensity; // 强度(如震动幅度、危险区域半径)
public bool revertsOnPhaseEnd; // 阶段结束时是否恢复
}
[Serializable]
public struct ArenaEventData
{
public ArenaEventType type;
public ArenaEventParams parameters;
public string sourceSkillId; // 来源技能 ID供物件做条件判断
}
```
### 8.4 ArenaEventBus单例
```csharp
public static class ArenaEventBus
{
static readonly Dictionary<string, List<IArenaInteractable>> _registry = new();
public static void Register(IArenaInteractable obj)
{
if (!_registry.TryGetValue(obj.ArenaObjectId, out var list))
_registry[obj.ArenaObjectId] = list = new List<IArenaInteractable>();
list.Add(obj);
}
public static void Unregister(IArenaInteractable obj) { /* ... */ }
public static void Dispatch(ArenaEventTrigger trigger)
{
var data = new ArenaEventData
{
type = trigger.eventType,
parameters = trigger.parameters,
sourceSkillId = "" // 由调用方填入
};
if (string.IsNullOrEmpty(trigger.targetArenaObjectId))
{
// 广播给所有注册物件
foreach (var list in _registry.Values)
foreach (var obj in list) obj.OnBossArenaEvent(data);
}
else if (_registry.TryGetValue(trigger.targetArenaObjectId, out var targets))
{
foreach (var obj in targets) obj.OnBossArenaEvent(data);
}
}
}
```
---
## 9. 平衡数据模板
### 9.1 BossSkillBalanceSheetSO 内联数据,用于策划填写)
```csharp
[Serializable]
public struct BossSkillBalanceNote
{
// ── 设计阶段填写(不参与运行时逻辑)──
[Header("威胁评估")]
public SkillThreatLevel threatLevel;
public CounterRewardLevel counterReward;
[Header("节奏设计")]
[Tooltip("此技能在战斗中的频率意图(低/中/高)")]
public SkillFrequencyHint frequencyHint;
[Tooltip("此技能是否作为阶段标志性技能")]
public bool isSignatureSkill;
[Header("学习曲线")]
[Tooltip("玩家第几次遭遇此 Boss 时通常能学会应对此技能")]
public int expectedLearnEncounter;
[Tooltip("正确应对此技能所需的前置技能/知识")]
[TextArea(1,3)]
public string prerequisiteKnowledge;
}
public enum SkillFrequencyHint { Rare, Occasional, Frequent }
```
### 9.2 平衡时序模板
策划在填写 `AttackPatternSO` 的时序数据时,参考以下基准:
| 技能类型 | 预警时长参考 | 前摇参考 | 后摇参考(脆弱窗口)|
|---------|-----------|---------|-----------------|
| 轻型近战 | 0.3-0.5s | 0.15-0.2s | 0.3-0.5s |
| 重型近战 | 0.7-1.0s | 0.3-0.5s | 0.6-1.0s |
| 冲刺 | 0.5-0.8s | 0.2s | 0.4-0.6s(撞墙后)|
| 单发弹射 | 0.5-0.7s | 0.2s | 0.3-0.5s |
| 多发弹幕 | 0.8-1.2s | 0.3s | 0.5-0.8s |
| 召唤技 | 1.0-1.5s | 0.5s | 1.0-2.0s(召唤期间脆弱)|
| 阶段技 | 1.5-2.5s(无法打断)| 0.5-1.0s | 全段脆弱 |
### 9.3 难度缩放协议
每个 `BossSkillSO` 对应的 `AttackPatternSO` 不直接存储难度缩放值;
缩放通过 `DifficultyScalerSO`(见 [29_DifficultySystem](./29_DifficultySystem.md))统一处理:
```
DifficultyScalerSO
├─ damageMultiplier → 作用于 DamageSourceSO.BaseDamage
├─ telegraphMultiplier → 作用于 AttackPatternSO.telegraphDurationEasy 加长 / Hard 缩短)
├─ recoveryMultiplier → 作用于 AttackPatternSO.recoveryDurationEasy 加长脆弱 / Hard 缩短)
└─ phaseTransitionDelay → 阶段转换动画时长Easy 加长逃跑时间)
```
---
## 10. 编辑器工作流
### 10.1 创建一个 Boss 技能的完整步骤
```
Step 1 — 在 Inspector 中填写 BossSkillSO
├─ 填写 skillId: {BossId}_{SkillName}(如 "SpiderGuard_WebShot"
├─ 选择 category 和 tags
├─ 选择 threatLevel 和 counterReward平衡笔记
└─ 填写 designNote一两句话说明该技能的设计意图
Step 2 — 创建对应 AttackPatternSO19_BossPatternLibrary §2
├─ 填写时序数据(参考 §9.2 时序模板)
├─ 配置 TelegraphConfig预警类型 + 资产)
├─ 配置 DamageSourceSO复用或新建
└─ 将 AttackPatternSO 拖入 BossSkillSO.attackPatterns[]
Step 3 — 配置脆弱窗口VulnerabilityWindowConfig
├─ 选择 triggerType通常 OnAttackRecovery
├─ 设置 duration 和 damageMultiplier
└─ 拖入 openFeedback / closeFeedback 预设
Step 4 — 配置玩家反制接口PlayerCounterResponse[]
├─ 为每种有效反制方式添加一个 Response 条目
├─ 设置对 Boss 的影响stagger / vulnWindow
└─ 设置对玩家的资源奖励
Step 5 — 将 BossSkillSO 添加到 BossPhaseConfigSO.patterns[]
└─ 注意BossPhaseConfigSO 中存放 AttackPatternSO
BossSkillSO 是对 AttackPatternSO 的上层包装,
BossSkillExecutor 通过 BossSkillSO 间接驱动 BossOrchestrator
Step 6 — 在 Editor PlayMode 中使用 BossSkillTestWindow 测试
├─ 选择 Boss Prefab
├─ 点击技能名称强制触发该技能
└─ 查看脆弱窗口和反制效果是否正常
```
### 10.2 BossSkillTestWindow编辑器工具
```csharp
// Editor/BossSkillTestWindow.cs
// 依赖:仅在 UnityEditor 命名空间下可用UNITY_EDITOR 宏保护)
public class BossSkillTestWindow : EditorWindow
{
GameObject _bossPrefab;
BossSkillSO _selectedSkill;
// 功能:
// 1. 在 PlayMode 中选择场景内 Boss列出其所有 BossSkillSO
// 2. 点击"强制触发"→ 调用 BossSkillExecutor.ForceExecuteSkill(skill)
// 3. 实时显示当前脆弱窗口状态(时长倒计时 + 伤害倍率)
// 4. 显示最近 10 次技能触发记录(时间戳 + 玩家是否成功反制)
}
```
---
## 11. 事件频道扩展
以下事件频道为 `BossSkillSystem` 专有,在 `00_Overview §7` 频道清单基础上补充:
| 频道 SO 名称 | 类型 | 数据 | 说明 |
|------------|------|------|------|
| `BossSkill_OnSkillStarted` | `StringEventChannelSO` | skillId | 技能开始执行时广播 |
| `BossSkill_OnSkillEnded` | `StringEventChannelSO` | skillId | 技能结束时广播 |
| `BossSkill_OnVulnWindowOpened` | `VoidEventChannelSO` | — | 脆弱窗口开启 |
| `BossSkill_OnVulnWindowClosed` | `VoidEventChannelSO` | — | 脆弱窗口关闭 |
| `BossSkill_OnCounterSuccess` | `StringEventChannelSO` | counterType | 玩家反制成功 |
| `BossSkill_OnGrantSoulPower` | `IntEventChannelSO` | 灵力数量 | 反制奖励灵力 |
| `BossSkill_OnGrantSpiritPower` | `IntEventChannelSO` | 魄元数量 | 反制奖励魄元 |
| `BossSkill_OnArenaEventTriggered` | `StringEventChannelSO` | eventType | 场景联动事件触发 |
| `BossSkill_OnSequenceStarted` | `StringEventChannelSO` | sequenceId | 技能序列开始 |
| `BossSkill_OnSequenceEnded` | `StringEventChannelSO` | sequenceId | 技能序列结束 |
---
## 12. 资产路径规范
```
Assets/ScriptableObjects/Enemies/Boss/
├── {BossId}/
│ ├── Skills/
│ │ ├── BSK_{BossId}_{SkillName}.asset ← BossSkillSO
│ │ └── SEQ_{BossId}_{SequenceName}.asset ← SkillSequenceSO可选
│ ├── Phases/
│ │ ├── BPC_{BossId}_Phase1.asset ← BossPhaseConfigSO来自 19
│ │ └── ...
│ ├── Patterns/
│ │ └── AP_{BossId}_{PatternName}.asset ← AttackPatternSO来自 19
│ └── Resources/
│ └── BRC_{BossId}_Rage.asset ← BossResourceConfigSO可选
└── Shared/
└── DamageSource/
└── DS_Boss_{Type}.asset ← 多 Boss 复用的 DamageSourceSO
```
命名约定:
- `BSK_` — BossSkillSO
- `SEQ_` — SkillSequenceSO
- `BPC_` — BossPhaseConfigSO
- `AP_` — AttackPatternSO
- `BRC_` — BossResourceConfigSO
- `DS_` — DamageSourceSO