# 19 · Boss 攻击模式库(Boss Pattern Library) > **命名空间** `BaseGames.Enemies.Boss.Patterns` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **依赖** `BaseGames.Enemies` · `BaseGames.Combat` · `BaseGames.Feedback` · `BaseGames.Core.Events` · BehaviorDesigner · Animancer --- ## 目录 1. [系统总览](#1-系统总览) 2. [攻击模式数据层](#2-攻击模式数据层) 3. [BossOrchestrator — 运行时编排器](#3-bossorchestrator--运行时编排器) 4. [TelegraphSystem — 预警系统](#4-telegraphsystem--预警系统) 5. [阶段转换规则](#5-阶段转换规则) 6. [内置攻击模式类型](#6-内置攻击模式类型) 7. [Boss 原型模板](#7-boss-原型模板) 8. [BehaviorDesigner 集成](#8-behaviordesigner-集成) 9. [事件频道](#9-事件频道) 10. [编辑器工具](#10-编辑器工具) --- ## 1. 系统总览 Boss 攻击模式系统将 Boss 战的**决策**与**执行**分离: ``` Boss 模式系统职责: ├─ AttackPatternSO → 单个攻击的完整数据(前摇/活跃/后摇/伤害/移动/预警) ├─ BossPhaseConfigSO → 一个阶段的模式集合(权重、冷却、组合规则) ├─ BossOrchestrator → 运行时编排:选模式 → 执行 → 监听结果 ├─ TelegraphSystem → 攻击前的视觉/音效预警(Surface Marker、闪光、UI 箭头) └─ PhaseTransitionRule → HP 阈值 → 触发阶段切换 ``` **设计原则**: - `AttackPatternSO` 完全数据化,美术/策划可在 Inspector 中配置 - BehaviorDesigner 调用 `BossOrchestrator` 的 **Action Task**,不直接操作动画 - 阶段切换通过 SO 事件频道广播,不在 BossBase 内硬编码 --- ## 2. 攻击模式数据层 ### AttackPatternSO — 单个攻击模式 ```csharp [CreateAssetMenu(menuName = "Enemies/Boss/AttackPattern")] public class AttackPatternSO : ScriptableObject { [Header("基础信息")] public string patternId; // 唯一 ID,用于动画事件映射 public string displayName; // 编辑器显示名 [Header("时序(秒)")] public float telegraphDuration; // 预警时长(玩家反应窗口) public float windupDuration; // 前摇(动画加速,不可取消) public float activeDuration; // 活跃帧(HitBox 开启) public float recoveryDuration; // 后摇(可被打断的脆弱期) [Header("伤害")] public DamageSourceSO damageSource; // 复用战斗系统的伤害描述 SO public bool isParryable; // 是否可弹反 public KnockbackProfile knockback; [Header("运动控制")] public bool lockBossMovement; // 前摇/活跃期间锁定 Boss 移动 public AnimationCurve movementCurve; // Boss 位移曲线(空 = 不移动) public float movementDistance; // 冲刺/位移距离 [Header("投射物")] public ProjectileConfigSO[] projectiles; // 发射的弹射物(可多个) public Vector2[] projectileDirections; // 对应发射方向 [Header("预警配置")] public TelegraphConfig telegraph; // 预警类型及参数(见 §4) [Header("权重与冷却")] [Range(1, 10)] public int weight; // 选择权重(越高越常被选中) public float cooldown; // 同一模式的最小复用间隔(秒) [Header("条件")] public PatternCondition[] activationConditions; // 激活条件(距离/玩家位置/HP范围) } ``` ### PatternCondition — 激活条件 ```csharp [Serializable] public struct PatternCondition { public ConditionType type; // ── InRange ── public float minRange; public float maxRange; // ── HPBelow / HPAbove ── [Range(0f, 1f)] public float hpThreshold; // ── PlayerIsAbove / PlayerIsBelow / PlayerIsBehind ── // 无额外参数 } public enum ConditionType { InRange, // 玩家在 [minRange, maxRange] 内 OutOfRange, // 玩家在 maxRange 外 HPBelow, // Boss HP < hpThreshold HPAbove, // Boss HP > hpThreshold PlayerIsAbove, // 玩家高于 Boss(触发对空攻击) PlayerIsBelow, // 玩家低于 Boss(触发下方攻击) PlayerIsBehind, // 玩家在 Boss 身后(触发转身攻击) Always, // 无条件(默认) } ``` ### BossPhaseConfigSO — 阶段配置 ```csharp [CreateAssetMenu(menuName = "Enemies/Boss/PhaseConfig")] public class BossPhaseConfigSO : ScriptableObject { [Header("阶段信息")] public int phaseIndex; // 0 = 第一阶段 public string phaseName; public Color phaseColor; // Boss HP 条颜色(用于区分阶段) [Header("可用模式")] public AttackPatternSO[] patterns; [Header("休息间隔")] public float minIdleGap; // 两次攻击之间最小空闲(秒) public float maxIdleGap; // 两次攻击之间最大空闲(秒) [Header("连招规则")] public int maxComboCount; // 最多连续 n 次不同模式再强制休息 public bool allowRepeatPattern; // 是否允许同一模式连续出现 [Header("阶段过渡特效")] public FeedbackPresetSO transitionFeedback; // 阶段切换时的 MMF_Player 预设 } ``` --- ## 3. BossOrchestrator — 运行时编排器 `BossOrchestrator` 挂载于 BossBase 所在 GameObject,负责模式选择与执行状态追踪。 ```csharp namespace BaseGames.Enemies.Boss.Patterns { public class BossOrchestrator : MonoBehaviour { [Header("配置")] [SerializeField] BossPhaseConfigSO[] _phases; // 所有阶段配置,按 phaseIndex 排列 [SerializeField] TelegraphSystem _telegraph; // 预警组件 [Header("事件频道")] [SerializeField] IntEventChannelSO _onBossPhaseChanged; // 发布(传入新阶段索引) [SerializeField] VoidEventChannelSO _onBossVulnerable; // 后摇期间发布(玩家可追打提示) [SerializeField] StringEventChannelSO _onPatternStarted; // 发布 patternId(音频/镜头响应) // ── 运行时状态 ── BossPhaseConfigSO _currentPhase; AttackPatternSO _currentPattern; PatternState _state; float _stateTimer; int _comboCounter; readonly Dictionary _cooldownTimers = new(); public bool IsExecutingPattern => _state != PatternState.Idle; public AttackPatternSO CurrentPattern => _currentPattern; // ──────────────────────────────────────────── // 公开 API(供 BehaviorDesigner Tasks 调用) // ──────────────────────────────────────────── public void SetPhase(int phaseIndex) { _currentPhase = _phases[phaseIndex]; _comboCounter = 0; _onBossPhaseChanged.Raise(phaseIndex); } /// /// 选择并开始执行一个合适的攻击模式。 /// 返回 false 时表示没有可用模式(AI 应等待后重试)。 /// public bool TryExecutePattern(Vector2 playerPosition) { if (_state != PatternState.Idle) return false; var pattern = SelectPattern(playerPosition); if (pattern == null) return false; StartPattern(pattern); return true; } public void AbortCurrentPattern() { StopAllCoroutines(); _state = PatternState.Idle; _currentPattern = null; } // ──────────────────────────────────────────── // 内部逻辑 // ──────────────────────────────────────────── AttackPatternSO SelectPattern(Vector2 playerPos) { float distToPlayer = Vector2.Distance(transform.position, playerPos); bool playerAbove = playerPos.y > transform.position.y + 0.5f; // 1. 筛选:满足条件 + 冷却完毕 var candidates = new List<(AttackPatternSO pat, int weight)>(); foreach (var p in _currentPhase.patterns) { if (!IsCooledDown(p)) continue; if (!CheckConditions(p, distToPlayer, playerAbove)) continue; if (!_currentPhase.allowRepeatPattern && p == _currentPattern) continue; candidates.Add((p, p.weight)); } if (candidates.Count == 0) return null; // 强制休息检查 if (_comboCounter >= _currentPhase.maxComboCount) return null; // 2. 加权随机选择 int totalWeight = candidates.Sum(c => c.weight); int roll = UnityEngine.Random.Range(0, totalWeight); int accumulated = 0; foreach (var (pat, w) in candidates) { accumulated += w; if (roll < accumulated) return pat; } return candidates[^1].pat; } void StartPattern(AttackPatternSO pattern) { _currentPattern = pattern; _state = PatternState.Telegraph; _comboCounter++; _cooldownTimers[pattern] = Time.time; _onPatternStarted.Raise(pattern.patternId); StartCoroutine(ExecutePatternRoutine(pattern)); } IEnumerator ExecutePatternRoutine(AttackPatternSO p) { // ── 预警阶段 ── _telegraph.ShowTelegraph(p.telegraph); yield return new WaitForSeconds(p.telegraphDuration); _telegraph.HideTelegraph(); // ── 前摇 ── _state = PatternState.Windup; yield return new WaitForSeconds(p.windupDuration); // ── 活跃帧(动画事件触发 HitBox,此处设移动曲线)── _state = PatternState.Active; yield return new WaitForSeconds(p.activeDuration); // ── 后摇(脆弱期)── _state = PatternState.Recovery; _onBossVulnerable.Raise(); yield return new WaitForSeconds(p.recoveryDuration); // ── 完毕 ── _state = PatternState.Idle; _currentPattern = null; } bool IsCooledDown(AttackPatternSO p) => !_cooldownTimers.TryGetValue(p, out float last) || Time.time - last >= p.cooldown; bool CheckConditions(AttackPatternSO p, float dist, bool playerAbove) { foreach (var cond in p.activationConditions) { if (!EvaluateCondition(cond, dist, playerAbove)) return false; } return true; } bool EvaluateCondition(PatternCondition c, float dist, bool playerAbove) => c.type switch { ConditionType.InRange => dist >= c.minRange && dist <= c.maxRange, ConditionType.OutOfRange => dist > c.maxRange, ConditionType.PlayerIsAbove => playerAbove, ConditionType.PlayerIsBelow => !playerAbove, _ => true, }; void Update() { // 冷却定时器自然流逝(cooldownTimers 存储的是开始时间,不需要手动递减) } } public enum PatternState { Idle, Telegraph, Windup, Active, Recovery } } ``` --- ## 4. TelegraphSystem — 预警系统 Boss 攻击前通过多层视觉/音效预警给玩家反应时间。 ```csharp public class TelegraphSystem : MonoBehaviour { [Header("预警 Prefab")] [SerializeField] SpriteRenderer _flashOverlay; // Boss 躯体 sprite 闪红 [SerializeField] GameObject _groundMarkerPrefab; // 地面危险标记(AOE 落点) [SerializeField] GameObject _directionArrowPrefab; // 方向预警箭头(冲刺) [SerializeField] AudioEventSO _telegraphSFX; // 预警音效频道 public void ShowTelegraph(TelegraphConfig config) { switch (config.type) { case TelegraphType.BodyFlash: StartCoroutine(FlashRoutine(config.flashColor, config.duration)); break; case TelegraphType.GroundMarker: SpawnGroundMarker(config.targetPosition, config.radius); break; case TelegraphType.DirectionArrow: ShowDirectionArrow(config.direction); break; case TelegraphType.FullBodyGlow: SetBodyGlow(config.glowColor, config.duration); break; } _telegraphSFX?.Raise(); } public void HideTelegraph() { _flashOverlay.color = Color.white; // 隐藏所有活跃的地面标记 / 方向箭头 } // ... 各预警类型实现 } [Serializable] public struct TelegraphConfig { public TelegraphType type; public Color flashColor; // BodyFlash / FullBodyGlow 颜色 public float duration; // 闪烁/发光持续时长 public Vector2 targetPosition; // GroundMarker 目标位置 public float radius; // GroundMarker 半径 public Vector2 direction; // DirectionArrow 方向 } public enum TelegraphType { None, BodyFlash, // Boss 躯体快速变色闪烁 GroundMarker, // 地面出现危险区域标记(红色圆圈) DirectionArrow, // 在 Boss 前方显示冲刺方向箭头 FullBodyGlow, // Boss 全身发光(强攻击专用,通常配合音效) } ``` --- ## 5. 阶段转换规则 ```csharp [CreateAssetMenu(menuName = "Enemies/Boss/PhaseTransitionRule")] public class PhaseTransitionRuleSO : ScriptableObject { [Header("触发条件")] [Range(0f, 1f)] public float hpThreshold; // HP 降到此比例以下触发 [Header("目标阶段")] public int targetPhaseIndex; [Header("过渡演出")] public float invincibilityDuration; // 过渡期间无敌时长(Boss 播放嘲讽/变身动画) public bool healPartial; // 是否恢复部分 HP(如恢复至下一阶段起始 HP) [Range(0f, 1f)] public float partialHealAmount; // 恢复到 HP 总量的 x% } ``` **BossBase 集成**(在 `06_EnemySystem.md §5 BossBase` 中追加): ```csharp // BossBase.cs — 扩展阶段切换逻辑 [SerializeField] PhaseTransitionRuleSO[] _transitionRules; [SerializeField] BossOrchestrator _orchestrator; protected override void OnHPChanged(int newHP) { float ratio = (float)newHP / _stats.maxHP; foreach (var rule in _transitionRules) { if (ratio <= rule.hpThreshold && !_triggeredPhases.Contains(rule.targetPhaseIndex)) { _triggeredPhases.Add(rule.targetPhaseIndex); StartCoroutine(ExecutePhaseTransition(rule)); break; } } } IEnumerator ExecutePhaseTransition(PhaseTransitionRuleSO rule) { // 1. 进入无敌状态 SetInvincible(true); _orchestrator.AbortCurrentPattern(); // 2. 播放过渡演出反馈(MMF_Player: 画面震动 + 色彩分离) _transitionFeedback?.PlayFeedbacks(); yield return new WaitForSeconds(rule.invincibilityDuration); // 3. 切换阶段 _orchestrator.SetPhase(rule.targetPhaseIndex); SetInvincible(false); } ``` --- ## 6. 内置攻击模式类型 ### 6.1 近战冲刺(MeleeLunge) ``` Telegraph: DirectionArrow(朝玩家方向箭头,0.5s) Windup: 0.2s(下蹲姿势) Active: 0.15s(HitBox开启 + Rigidbody2D 沿 movementCurve 冲刺) Recovery: 0.5s(滑步停止,Boss 转向玩家) DamageType: Melee · Knockback: Medium isParryable: ✓ 推荐 weight: 4 · cooldown: 1.5s ``` ### 6.2 投射物连射(ProjectileVolley) ``` Telegraph: BodyFlash(橙色,0.6s) Windup: 0.3s(举起武器蓄力) Active: 0.8s(动画事件每 0.2s 生成一颗弹射物,共 3~5 颗) Recovery: 0.4s DamageType: Projectile · isParryable: ✓(弹射物可弹反) 推荐 weight: 3 · cooldown: 3s ``` ### 6.3 范围打击(AreaDenial) ``` Telegraph: GroundMarker(玩家脚下红圈,0.8s) Windup: 0.4s(跳跃升空) Active: 0.1s(砸地,生成范围 HitBox) Recovery: 0.6s(落地后摇) DamageType: Melee · AoE · isParryable: ✗ 推荐 weight: 2 · cooldown: 4s 条件: InRange(0, 4) ``` ### 6.4 全屏横扫(HorizontalSweep) ``` Telegraph: FullBodyGlow(红色,1.0s) Windup: 0.5s Active: 0.3s(持续横向 HitBox 覆盖全屏宽) Recovery: 0.8s(Boss 喘息) DamageType: Melee · Heavy · isParryable: ✗ 推荐 weight: 1 · cooldown: 8s 条件: HPBelow(0.4)(仅在第二阶段以下使用) ``` ### 6.5 多段连击(MultiHitCombo) ``` Telegraph: BodyFlash(白色,0.3s) Windup: 0.1s Active: 1.2s(3次HitBox依次开启,间隔0.3s,最后一击可弹反) Recovery: 0.6s DamageType: Melee · Light(1), Light(1), Medium(2) isParryable: 第3击 ✓ 推荐 weight: 5 · cooldown: 2s ``` --- ## 7. Boss 原型模板 ### 7.1 敏捷近战 Boss(AgileKnight) **设计核心**:高移动速度、多次冲刺、强调弹反互动。 ``` 阶段 1(HP 100%~50%): 模式集: MeleeLunge(w4) · MultiHitCombo(w5) · ProjectileVolley(w2) IdleGap: 0.8~1.5s · MaxCombo: 3 阶段 2(HP 50%~0%): 模式集: MeleeLunge(w6, cooldown减半) · MultiHitCombo(w5) · HorizontalSweep(w2, 仅HP<30%) IdleGap: 0.3~1.0s · MaxCombo: 4 过渡: 1.5s无敌 + MMF 色调变红 + 速度提升 1.4× ``` ### 7.2 远程投射 Boss(SorcererBoss) **设计核心**:与玩家保持距离、多种弹道类型、Arena 控制。 ``` 阶段 1(HP 100%~60%): 模式集: ProjectileVolley(w5) · AreaDenial(w3) 条件: OutOfRange(5) 时强制使用 TeleportBehindPlayer 模式 IdleGap: 1.0~2.0s 阶段 2(HP 60%~0%): 新增模式: HomingProjectileSpray(向玩家发射3颗追踪弹) IdleGap: 0.6~1.5s 过渡: 传送至场地中央 + FullBodyGlow 2s + 特殊动画 ``` ### 7.3 巨型多阶段 Boss(ColossalBoss) **设计核心**:3个阶段、每阶段改变整体行为模式、标志性大招。 ``` 阶段 1(HP 100%~70%): 模式集: GroundSlam · MeleeLunge 弱点部位: HurtBox 仅在头部 阶段 2(HP 70%~35%): 新增模式: WallJump + AreaDenial组合(Boss跳墙后俯冲) 弱点部位: 头部 + 双手(3个 HurtBox) 阶段 3(HP 35%~0%): HorizontalSweep + ProjectileVolley 组合使用 IdleGap 减至 0.3s 背景音乐切换至最终阶段曲 弱点部位: 全身开放 ``` --- ## 8. BehaviorDesigner 集成 ### 自定义 Action Tasks ```csharp // AI/Actions/Boss/ExecutePatternAction.cs [TaskCategory("Boss/Orchestrator")] [TaskDescription("请求编排器执行一个攻击模式。成功 = 找到并开始了模式;失败 = 无可用模式(需等待)")] public class ExecutePatternAction : Action { [RequiredField] public SharedGameObject bossGO; [RequiredField] public SharedTransform playerTransform; BossOrchestrator _orchestrator; public override void OnStart() => _orchestrator = bossGO.Value.GetComponent(); public override TaskStatus OnUpdate() { if (_orchestrator.IsExecutingPattern) return TaskStatus.Running; bool started = _orchestrator.TryExecutePattern(playerTransform.Value.position); return started ? TaskStatus.Running : TaskStatus.Failure; } } // AI/Actions/Boss/SetBossPhaseAction.cs [TaskCategory("Boss/Orchestrator")] public class SetBossPhaseAction : Action { public SharedInt phaseIndex; BossOrchestrator _orchestrator; public override void OnStart() { _orchestrator = GetComponent(); _orchestrator.SetPhase(phaseIndex.Value); } public override TaskStatus OnUpdate() => TaskStatus.Success; } // AI/Conditions/Boss/IsPatternComplete.cs [TaskCategory("Boss/Orchestrator")] [TaskDescription("检查编排器是否已完成当前模式(处于 Idle 状态)")] public class IsPatternComplete : Conditional { BossOrchestrator _orchestrator; public override void OnStart() => _orchestrator = GetComponent(); public override TaskStatus OnUpdate() => _orchestrator.IsExecutingPattern ? TaskStatus.Failure : TaskStatus.Success; } ``` ### 典型 Boss 行为树结构 ``` Boss BehaviorTree └── Selector(优先检查阶段切换,再执行攻击) ├── Sequence(阶段切换检查) │ ├── Conditional: IsBossHPBelow(0.5) && !IsPhase2Active │ └── Action: SetBossPhaseAction(phaseIndex=1) │ └── Sequence(攻击循环) ├── Action: UpdatePlayerPosition (更新黑板变量) ├── Action: FacePlayer (转向玩家) ├── Selector(执行攻击或等待) │ ├── Action: ExecutePatternAction(尝试执行模式) │ └── Action: WaitRandom(0.3, 1.0)(无可用模式时等待) └── Action: IsPatternComplete (等待模式完成再循环) ``` --- ## 9. 事件频道 | 频道资产 | 类型 | 发布方 | 主要订阅方 | |---------|------|--------|----------| | `OnBossPhaseChanged.asset` | `IntEventChannelSO` | `BossOrchestrator` | `BGMController`(切音乐)、`BossHPBar`(切颜色)、`CameraStateController`(切镜头) | | `OnBossVulnerable.asset` | `VoidEventChannelSO` | `BossOrchestrator` | `UIManager`(显示"追打!"提示)、`PlayerFeedback`(提示音效)| | `OnBossPatternStarted.asset` | `StringEventChannelSO` | `BossOrchestrator` | `AudioManager`(模式专属音效)、`CameraStateController`(镜头跟踪模式) | | `OnBossDefeated.asset` | `StringEventChannelSO` | `BossBase.OnDeath()` | `GameManager`、`ProgressionSystem`、`CutsceneManager` | --- ## 10. 编辑器工具 ### BossPatternPreview — Inspector 实时预览 `AttackPatternSO` 自定义 Inspector 显示时序甘特图: ``` ┌─ AttackPatternSO: MeleeLunge ──────────────────────────────┐ │ 时序(总计 1.35s): │ │ [预警████0.5s][前摇██0.2s][活跃█0.15s][后摇█████0.5s] │ │ ───────────────────────────────────────────────────── │ │ 伤害: 2 · 可弹反: ✓ · 权重: 4 · 冷却: 1.5s │ │ 条件: 无 │ │ ───────────────────────────────────────────────────── │ │ [在 Scene 中预览预警] [在 Game 视图模拟执行] │ └────────────────────────────────────────────────────────────┘ ``` ### BossPhaseFlowGraph — EditorWindow `Tools > Zeling > Boss Phase Flow` 显示: - 所有 Boss Prefab 的阶段节点图 - HP 阈值触发箭头 - 每个阶段的模式列表(权重可视化为饼图) - 点击模式节点 → 跳转到对应 `AttackPatternSO`