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

33 KiB
Raw Permalink Blame History

47 · Boss 技能系统框架Boss Skill System Framework

命名空间 BaseGames.Enemies.Boss.Skills
所属文档集 ← 返回索引 · 总览
依赖文档


目录

  1. 系统定位与层次关系
  2. BossSkillSO — 技能数据层
  3. Boss 技能分类体系
  4. 弱点与脆弱窗口系统
  5. 玩家反制接口
  6. Boss 技能序列系统
  7. Boss 资源系统(愤怒 / 状态充能)
  8. 场景联动接口
  9. 平衡数据模板
  10. 编辑器工作流
  11. 事件频道扩展
  12. 资产路径规范

1. 系统定位与层次关系

1.1 为什么需要 BossSkillSystem

19_BossPatternLibraryAttackPatternSO 描述单次攻击动作(前摇/活跃帧/后摇/弹射物),
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 技能必须在开发前确定其 BossSkillTypeInteractionTag
  2. 反制可读性 — 每个技能必须明确"玩家用什么技能/动作可以反制/利用"
  3. 脆弱窗口强制存在 — 每个技能至少有一个 VulnerabilityWindow(后摇 ≥ 0.5s 或专属弱点)
  4. 不与 AttackPatternSO 重复 — 伤害数值/时序数据保留在 AttackPatternSO不在 BossSkillSO 中重复

2. BossSkillSO — 技能数据层

[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

public enum BossSkillCategory
{
    // ── 主动攻击 ──
    Melee,           // 近战物理攻击(覆盖正前方/扇形/冲刺)
    Ranged,          // 远程弹射物攻击
    Charge,          // 冲刺突进类
    AoE,             // 全场/大范围爆炸类
    Environmental,   // 激活/改变场景(召唤陷阱/破坏平台/生成危险区域)
    Summon,          // 召唤小怪/分身/辅助体

    // ── 特殊状态 ──
    Buff,            // Boss 自身增益(加速/护甲/无敌)
    Debuff,          // 对玩家施加负面状态(减速/沉默/中毒/禁锢)
    Phase,           // 阶段转换技(仅在 HP 阈值触发,不参与随机选择)

    // ── 被动 ──
    Passive,         // 持续生效的被动机制(不通过 BossOrchestrator 选取)
    Reactive,        // 响应玩家行为的反应技(玩家使用技能 → Boss 反制)
}

3.2 交互标签InteractionTag

可多选的属性标记,用于确定技能与玩家系统的交互方式:

[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 击杀后阶段转换 / 大量灵力 阶段转换技
public enum SkillThreatLevel { Low, Mid, High, Lethal }
public enum CounterRewardLevel { None, Small, Medium, Large, Phase }
// 两者都作为 BossSkillSO 的设计标注字段(不参与运行时逻辑)

4. 弱点与脆弱窗口系统

4.1 VulnerabilityWindowConfig

定义 Boss 在执行技能何时、何处、如何暴露弱点:

[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运行时组件

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

[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 反制接口的运行时处理

// 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

[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

/// <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

[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运行时

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

/// <summary>
/// 场景中可被 Boss 技能交互的对象实现此接口。
/// 无需引用 BossBoss 通过 ArenaEventBus 广播,场景监听并响应。
/// </summary>
public interface IArenaInteractable
{
    string ArenaObjectId { get; } // 唯一标识(在 BossSkillSO.arenaEvents 中引用)
    void OnBossArenaEvent(ArenaEventData data);
}

8.3 ArenaEventTrigger & ArenaEventData

[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单例

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 内联数据,用于策划填写)

[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)统一处理:

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编辑器工具

// 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