# 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 { /// /// 挂载于 BossBase,追踪并管理当前活跃的脆弱窗口。 /// 由 BossSkillExecutor 在技能执行过程中驱动。 /// 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 /// /// 运行 SkillSequenceSO 的协程控制器,挂载于 BossBase。 /// 由 BehaviorDesigner 的 Action Task RunBossSequence 调用。 /// 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 /// /// 场景中可被 Boss 技能交互的对象实现此接口。 /// 无需引用 Boss;Boss 通过 ArenaEventBus 广播,场景监听并响应。 /// 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> _registry = new(); public static void Register(IArenaInteractable obj) { if (!_registry.TryGetValue(obj.ArenaObjectId, out var list)) _registry[obj.ArenaObjectId] = list = new List(); 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 BossSkillBalanceSheet(SO 内联数据,用于策划填写) ```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.telegraphDuration(Easy 加长 / Hard 缩短) ├─ recoveryMultiplier → 作用于 AttackPatternSO.recoveryDuration(Easy 加长脆弱 / Hard 缩短) └─ phaseTransitionDelay → 阶段转换动画时长(Easy 加长逃跑时间) ``` --- ## 10. 编辑器工作流 ### 10.1 创建一个 Boss 技能的完整步骤 ``` Step 1 — 在 Inspector 中填写 BossSkillSO ├─ 填写 skillId: {BossId}_{SkillName}(如 "SpiderGuard_WebShot") ├─ 选择 category 和 tags ├─ 选择 threatLevel 和 counterReward(平衡笔记) └─ 填写 designNote(一两句话说明该技能的设计意图) Step 2 — 创建对应 AttackPatternSO(19_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