675 lines
24 KiB
Markdown
675 lines
24 KiB
Markdown
# 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<AttackPatternSO, float> _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);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 选择并开始执行一个合适的攻击模式。
|
||
/// 返回 false 时表示没有可用模式(AI 应等待后重试)。
|
||
/// </summary>
|
||
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<BossOrchestrator>();
|
||
|
||
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<BossOrchestrator>();
|
||
_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<BossOrchestrator>();
|
||
|
||
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`
|