# 54 · 霸体系统(Poise / Superarmor System) > **命名空间** `BaseGames.Combat` > **所属文档集** [← 返回索引](./README.md) · [总览](./00_Overview.md) > **依赖** `BaseGames.Combat`(DamageInfo / HitBox / HurtBox)· `BaseGames.Skills`(FormSkillSO)· `BaseGames.Enemies.Boss.Skills`(BossSkillSO) --- ## 目录 1. [系统总览](#1-系统总览) 2. [核心枚举定义](#2-核心枚举定义) 3. [霸体窗口配置(PoiseWindowConfig)](#3-霸体窗口配置poiseswindowconfig) 4. [IPoiseSource — 霸体来源接口](#4-ipoisesource--霸体来源接口) 5. [HurtBox 打断判定流水线](#5-hurtbox-打断判定流水线) 6. [DamageInfo / DamageSourceSO 扩展](#6-damageinfo--damagesourceso-扩展) 7. [玩家霸体配置](#7-玩家霸体配置) - [7.1 攻击状态霸体](#71-攻击状态霸体) - [7.2 技能施放霸体(FormSkillSO)](#72-技能施放霸体formskillso) - [7.3 能力状态霸体](#73-能力状态霸体) 8. [敌人 / Boss 霸体配置(BossSkillSO)](#8-敌人--boss-霸体配置bossskillso) 9. [显式打断关系表(PoiseOverrideTableSO)](#9-显式打断关系表poiseoverridetableso) 10. [全动作霸体参考表](#10-全动作霸体参考表) 11. [平衡设计准则](#11-平衡设计准则) 12. [编辑器友好设计](#12-编辑器友好设计) --- ## 1. 系统总览 **霸体(Poise)** 是动作游戏中"受击时不被打断"的能力。本系统将霸体和打断能力拆解为两个对立等级,并通过 SO 数据驱动实现对**所有技能、攻击、能力**的精细配置。 ### 核心概念 | 概念 | 说明 | |------|------| | **霸体等级(PoiseLevel)** | 当前动作抵抗被打断的强度。等级越高,越难被打断。 | | **打断等级(BreakLevel)** | 攻击/技能的打断能力。等级越高,能打断越强的霸体。 | | **霸体窗口(Poise Window)** | 某个动作在哪段时间内拥有霸体(可以是整个状态,也可以是特定动画帧区间)。 | | **霸体 vs 无敌帧(IFrame)** | 无敌帧 = 不受任何伤害;霸体 = 受伤但不被打断,两者独立,可同时生效。 | ### 打断判定规则 ``` 受击时: 1. 检查无敌帧(IFrame) → 若活跃,直接跳过所有伤害处理 2. 检查打断逻辑: a. 查询 PoiseOverrideTable 是否有该攻击 vs 该状态的显式规则 → 若有 AlwaysInterrupt: 强制打断(Unbreakable 除外) → 若有 NeverInterrupt: 绝不打断(保留伤害) b. 默认规则:(int)incomingBreakLevel >= (int)currentPoiseLevel → 打断 3. 若打断:进入 HurtState / 施加击退 / 技能 / 动作被取消 若不打断:仅扣血 + 播放受击闪烁,不进入 HurtState ``` ``` 装备系统 职责图: ├─ PoiseLevel / BreakLevel → 两个对立枚举(等级比较核心) ├─ PoiseWindowConfig → 结构体(哪段时间有霸体,霸体等级) ├─ IPoiseSource → 接口(状态/技能/动作暴露当前霸体等级) ├─ DamageSourceSO → 增加 breakLevel 字段 ├─ DamageInfo → 增加 BreakLevel 字段 ├─ HurtBox → 打断判定逻辑 ├─ FormSkillSO → 技能施放期间的霸体窗口 ├─ BossSkillSO → Boss 技能执行期间的霸体配置 ├─ PlayerStateBase → 玩家状态暴露 CurrentPoise └─ PoiseOverrideTableSO → 显式打断关系配置(可选精细控制) ``` --- ## 2. 核心枚举定义 ```csharp namespace BaseGames.Combat { /// /// 霸体等级:当前动作抵抗被打断的强度。 /// Unbreakable = 100,任何 BreakLevel 均无法打断(BOSS 阶段转换技、玩家特定能力专用)。 /// public enum PoiseLevel { None = 0, // 无霸体:任何攻击均可打断(普通状态、普通敌人站立) Light = 1, // 轻霸体:可被中级以上攻击打断(普通攻击第3段可打断) Medium = 2, // 中霸体:只有重型攻击或技能可打断(精英怪冲刺、玩家技能施放) Heavy = 3, // 重霸体:只有破甲攻击可打断(Boss 核心攻击前摇) Unbreakable = 100, // 霸体:完全不可打断(Boss 阶段过渡、剧情硬直) } /// /// 打断等级:攻击/技能打断对手霸体的能力。 /// 判定规则:(int)breakLevel >= (int)targetPoiseLevel 时发生打断(Unbreakable 例外)。 /// public enum BreakLevel { None = 0, // 无打断力(弱攻击,只能打断 PoiseLevel.None) Light = 1, // 轻打断(可打断 Light 及以下霸体) Medium = 2, // 中打断(可打断 Medium 及以下霸体) Heavy = 3, // 重打断(可打断 Heavy 及以下霸体) Breaker = 4, // 破甲(可打断 Heavy 及以下,不能打断 Unbreakable) } } ``` ### 打断关系速查矩阵 | **BreakLevel →** | None(0) | Light(1) | Medium(2) | Heavy(3) | Breaker(4) | |:---:|:---:|:---:|:---:|:---:|:---:| | **PoiseLevel.None(0)** | ✅打断 | ✅打断 | ✅打断 | ✅打断 | ✅打断 | | **PoiseLevel.Light(1)** | ❌ | ✅打断 | ✅打断 | ✅打断 | ✅打断 | | **PoiseLevel.Medium(2)** | ❌ | ❌ | ✅打断 | ✅打断 | ✅打断 | | **PoiseLevel.Heavy(3)** | ❌ | ❌ | ❌ | ✅打断 | ✅打断 | | **PoiseLevel.Unbreakable** | ❌ | ❌ | ❌ | ❌ | ❌ | > 所有 ❌ 情况:仍扣血,但**不进入 HurtState,不施加击退**。 --- ## 3. 霸体窗口配置(PoiseWindowConfig) ```csharp /// /// 霸体窗口配置。定义某动作在哪段时间内(以动画时间轴为基准)拥有霸体。 /// - 若 windowStart = windowEnd = 0,则整个动作期间均拥有霸体。 /// - windowStart/End 使用归一化时间(0.0 = 动画起始,1.0 = 动画结束)。 /// [Serializable] public struct PoiseWindowConfig { [Tooltip("霸体等级(None = 无霸体,Unbreakable = 完全不可打断)")] public PoiseLevel level; [Tooltip("霸体生效起始时间(归一化,0 = 动画开始)。0+0 = 全程霸体。")] [Range(0f, 1f)] public float windowStart; [Tooltip("霸体生效结束时间(归一化,0 = 动画结束 = 1.0 等价)。0+0 = 全程霸体。")] [Range(0f, 1f)] public float windowEnd; /// 是否在整个动作期间都有霸体(windowStart = windowEnd = 0 时视为全程) public bool IsFullDuration => windowStart == 0f && windowEnd == 0f; /// 检查指定归一化时间是否在霸体窗口内 public bool IsActiveAt(float normalizedTime) { if (level == PoiseLevel.None) return false; if (IsFullDuration) return true; return normalizedTime >= windowStart && normalizedTime <= windowEnd; } /// 预设:全程轻霸体 public static PoiseWindowConfig LightFull => new() { level = PoiseLevel.Light, windowStart = 0, windowEnd = 0 }; /// 预设:全程中霸体 public static PoiseWindowConfig MediumFull => new() { level = PoiseLevel.Medium, windowStart = 0, windowEnd = 0 }; /// 预设:全程重霸体 public static PoiseWindowConfig HeavyFull => new() { level = PoiseLevel.Heavy, windowStart = 0, windowEnd = 0 }; /// 预设:无霸体 public static PoiseWindowConfig None => new() { level = PoiseLevel.None, windowStart = 0, windowEnd = 0 }; } ``` --- ## 4. IPoiseSource — 霸体来源接口 所有可以提供霸体的对象(玩家状态、技能执行器、Boss 技能执行器)实现此接口: ```csharp /// /// 霸体来源接口。HurtBox 在打断判定时调用此接口查询当前霸体等级。 /// public interface IPoiseSource { /// 当前霸体等级(实时,随动画帧变化) PoiseLevel CurrentPoise { get; } } ``` **玩家端实现**:`PlayerController` 汇总多个 `IPoiseSource`(当前状态 + 技能执行器)并对外暴露最高霸体等级: ```csharp public class PlayerController : MonoBehaviour, IPoiseSource { // 汇总当前所有霸体来源,取最高等级 public PoiseLevel CurrentPoise { get { PoiseLevel best = _currentState?.CurrentPoise ?? PoiseLevel.None; PoiseLevel skill = _skillManager.CurrentPoise; return (int)skill > (int)best ? skill : best; } } } ``` --- ## 5. HurtBox 打断判定流水线 `HurtBox.ReceiveDamage(DamageInfo)` 新增霸体检查步骤: ```csharp public void ReceiveDamage(DamageInfo info) { // ── Step 1: 无敌帧检查 ────────────────────────────────────────────────── if (_owner is IInvincible inv && inv.IsInvincible && !info.Flags.HasFlag(DamageFlags.IgnoreIFrame)) return; // ── Step 2: 计算最终伤害 ───────────────────────────────────────────────── int finalDamage = info.DamageType == DamageType.True ? info.RawDamage : Mathf.Max(1, info.RawDamage - _defenseStat); // ── Step 3: 霸体打断检查 ───────────────────────────────────────────────── bool interrupted = ShouldInterrupt(info); // ── Step 4: 应用伤害 ───────────────────────────────────────────────────── _owner.TakeDamage(finalDamage); OnHitConfirmedChannel.Raise(info); OnHurt.Invoke(info); // ── Step 5: 条件性打断 ──────────────────────────────────────────────────── if (interrupted) { _owner.ApplyKnockback(info); _owner.ForceState(HurtState); // 取消当前动作,进入硬直 } else { // 仅播放受击闪烁/震屏,不打断动作 _owner.PlayHitFlash(); } } /// 综合三层规则判断是否发生打断 bool ShouldInterrupt(DamageInfo info) { // 获取当前霸体等级 PoiseLevel poise = (_owner as IPoiseSource)?.CurrentPoise ?? PoiseLevel.None; // Unbreakable 不可打断(即使有 ForceBreak 标记) if (poise == PoiseLevel.Unbreakable) return false; // Layer 1: 显式 PoiseOverrideTable 查询 if (_overrideTable != null) { PoiseOverrideResult? ov = _overrideTable.Query(info.SourceId, _owner.StateId); if (ov == PoiseOverrideResult.AlwaysInterrupt) return true; if (ov == PoiseOverrideResult.NeverInterrupt) return false; } // Layer 2: DamageFlags.ForceBreak — 无视霸体等级(Unbreakable 已在上面拦截) if (info.Flags.HasFlag(DamageFlags.ForceBreak)) return true; // Layer 3: 默认数值比较 return (int)info.BreakLevel >= (int)poise; } ``` ### 新增 DamageFlags ```csharp public enum DamageFlags { // ... 原有 flags ... CanBeParried = 1 << 0, Unblockable = 1 << 1, IgnoreIFrame = 1 << 2, PerfectParryOnly = 1 << 3, IsProjectile = 1 << 4, CanClash = 1 << 5, // 新增 ForceBreak = 1 << 6, // 强制打断目标当前动作(忽略霸体等级,Unbreakable 除外) NoKnockback = 1 << 7, // 打断时不施加击退(仅进入 HurtState 硬直) } ``` --- ## 6. DamageInfo / DamageSourceSO 扩展 ### DamageInfo 新增字段 ```csharp public struct DamageInfo { // ... 原有字段 ... /// /// 此次攻击的打断等级。由 DamageSourceSO.breakLevel 赋值, /// 弹射物等特殊攻击由创建者手动指定。 /// public BreakLevel BreakLevel; /// /// 攻击来源标识(用于 PoiseOverrideTable 查询)。 /// 格式:DamageSourceSO.sourceId 或 SkillSO.skillId。 /// public string SourceId; } ``` ### DamageSourceSO 新增字段 ```csharp public class DamageSourceSO : ScriptableObject { // ... 原有字段 ... [Header("霸体系统")] [Tooltip("此攻击的打断等级(决定能打断多高的霸体)")] public BreakLevel breakLevel = BreakLevel.None; [Tooltip("是否强制打断(ForceBreak)—— 无视目标霸体等级,Unbreakable 除外")] public bool forceBreak = false; } ``` `HitBox` 构建 `DamageInfo` 时: ```csharp var info = new DamageInfo { // ... 原有赋值 ... BreakLevel = _damageSource.breakLevel, SourceId = _damageSource.sourceId, // ForceBreak 标记 DamageFlags = _damageSource.forceBreak ? _damageSource.DamageFlags | DamageFlags.ForceBreak : _damageSource.DamageFlags, }; ``` --- ## 7. 玩家霸体配置 ### 7.1 攻击状态霸体 `PlayerStateBase` 提供默认实现;`AttackState` 根据当前武器动画帧动态更新霸体等级: ```csharp public abstract class PlayerStateBase : StateObject, IPoiseSource { /// 此状态的默认霸体等级(子类可覆盖) public virtual PoiseLevel CurrentPoise => PoiseLevel.None; /// 外部查询时使用的状态 ID(用于 PoiseOverrideTable) public virtual string StateId => GetType().Name; } public class AttackState : PlayerStateBase { // 从当前武器 SO 读取当前段的霸体配置 public override PoiseLevel CurrentPoise { get { WeaponSO w = _weaponManager.ActiveWeapon; PoiseWindowConfig cfg = _comboState switch { ComboState.Attack1 => w.attack1PoiseWindow, ComboState.Attack2 => w.attack2PoiseWindow, ComboState.Attack3 => w.attack3PoiseWindow, ComboState.AirAttack => w.airAttackPoiseWindow, ComboState.UpAttack => w.upAttackPoiseWindow, ComboState.DownAttack => w.downAttackPoiseWindow, _ => PoiseWindowConfig.None, }; float t = _animancer.Layers[0].CurrentState?.NormalizedTime ?? 0f; return cfg.IsActiveAt(t) ? cfg.level : PoiseLevel.None; } } } ``` `WeaponSO` 新增攻击霸体窗口字段(见 [53_WeaponSystem §2](./53_WeaponSystem.md)): ```csharp [Header("霸体配置(每段攻击)")] public PoiseWindowConfig attack1PoiseWindow; // 默认 None(普通轻击无霸体) public PoiseWindowConfig attack2PoiseWindow; public PoiseWindowConfig attack3PoiseWindow; // 通常配置 Light 霸体(重击前摇) public PoiseWindowConfig airAttackPoiseWindow; public PoiseWindowConfig upAttackPoiseWindow; public PoiseWindowConfig downAttackPoiseWindow; ``` ### 三形态武器攻击霸体预设 | 动作 | 天魂(SkyBlade)| 地魂(EarthHammer)| 命魂(LifeScythe)| |------|:-----------:|:-----------:|:-----------:| | Attack1 | None | None | None | | Attack2 | None | None | None | | Attack3 | Light(0.0-0.5 前摇)| Medium(全程)| Light(全程)| | AirAttack | None | None | None | | UpAttack | None | None | None | | DownAttack | None | None | None | ### 7.2 技能施放霸体(FormSkillSO) `FormSkillSO` 新增 `poiseWindow` 字段: ```csharp [Header("霸体配置")] [Tooltip("技能施放期间的霸体窗口。None = 可被任何攻击打断。")] public PoiseWindowConfig poiseWindow; ``` `SkillManager` 在技能施放期间作为 `IPoiseSource`: ```csharp public class SkillManager : MonoBehaviour, IPoiseSource { FormSkillSO _activeCastingSkill; float _castStartTime; public PoiseLevel CurrentPoise { get { if (_activeCastingSkill == null) return PoiseLevel.None; float elapsed = Time.time - _castStartTime; float duration = _activeCastingSkill.castLockDuration; float normalized = Mathf.Clamp01(duration > 0 ? elapsed / duration : 1f); return _activeCastingSkill.poiseWindow.IsActiveAt(normalized) ? _activeCastingSkill.poiseWindow.level : PoiseLevel.None; } } } ``` **九种技能施放霸体预设**: | 技能 | 形态 | 效果类型 | poiseWindow | |------|------|---------|------------| | 裂空掌 | 天魂 | MeleeAoE | `Light(0.0-0.6)` — 出手前摇有轻霸体 | | 漩灵击 | 天魂 | BarrierAura | `Medium(全程)` — 护盾持续期间中霸体 | | 灵踪弹 | 天魂 | Projectile | `None` — 远程技能无前摇霸体 | | 地行术 | 地魂 | GroundDive | `Unbreakable(全程)` — 入地期间完全无敌 | | 霸山拳 | 地魂 | MeleeAoE | `Heavy(0.0-0.4)` — 蓄力起手重霸体 | | 魂元爆 | 地魂 | DelayedExplosion | `Light(0.0-0.3)` — 放置前摇轻霸体 | | 登龙蹴 | 命魂 | DragonKick | `Heavy(全程)` — 升龙整段重霸体 | | 太虚斩 | 命魂 | WraithDash | `Medium(全程)` — 冲刺中霸体 | | 残阴术 | 命魂 | ShadowDecoy | `None` — 残影技能无霸体 | ### 7.3 能力状态霸体 | 状态类 | `CurrentPoise` 返回值 | 说明 | |--------|---------------------|------| | `IdleState` | `None` | 站立无霸体 | | `RunState` | `None` | 跑动无霸体 | | `AttackState` | 见 §7.1(动态) | 武器 SO 配置 | | `DashState` | `None`(使用 IFrame 代替)| 冲刺靠无敌帧保护 | | `AirState` | `None` | 空中无霸体 | | `SpringState` | `Heavy` | 灵泉治疗全程重霸体(不可轻易打断)| | `WallGrabState` | `Light` | 墙壁悬挂轻霸体(强击可推下)| | `ParryState` | `Medium` | 弹反动作中霸体(弹反窗口内)| | `HurtState` | `None` | 受击硬直无霸体 | | `DeathState` | `Unbreakable` | 死亡动画完整播放 | --- ## 8. 敌人 / Boss 霸体配置(BossSkillSO) `BossSkillSO` 新增霸体配置: ```csharp // ───────────────────────────── // 8. 霸体配置(新增) // ───────────────────────────── [Header("霸体配置")] [Tooltip("此技能执行期间的霸体窗口(None = 可被玩家攻击打断)")] public PoiseWindowConfig poiseWindow; ``` `AttackPatternSO`(`19_BossPatternLibrary`)也添加打断等级,以描述**单次动作模式**的打断能力: ```csharp [Header("打断能力")] [Tooltip("此攻击动作对玩家霸体的打断等级")] public BreakLevel breakLevel = BreakLevel.Light; ``` ### Boss 技能霸体分类建议 | Boss 技能类型 | 推荐 poiseWindow | |-------------|----------------| | `Melee` 近战普通攻击 | `Light(全程)` | | `Charge` 冲刺突进 | `Medium(全程)` | | `AoE` 大范围爆炸 | `Heavy(0.0-0.5 蓄力段)` | | `Phase` 阶段转换 | `Unbreakable(全程)` | | `Reactive` 反制技 | `Medium(全程)` | | `Buff` 自身增益 | `Heavy(全程)` | | `Summon` 召唤技 | `Light(全程)` | ### 普通敌人霸体(EnemyBase 扩展) 普通敌人通过 `EnemyConfigSO` 配置站立/攻击状态的霸体等级: ```csharp [Header("霸体配置")] public PoiseLevel idlePoise = PoiseLevel.None; // 站立/游荡时 public PoiseLevel attackPoise = PoiseLevel.Light; // 攻击动作时 public PoiseLevel staggerThreshold = PoiseLevel.None; // 受到同级霸体时触发僵直动画 ``` --- ## 9. 显式打断关系表(PoiseOverrideTableSO) 当默认数值规则不满足精细设计需求时,`PoiseOverrideTableSO` 允许指定**特定攻击 vs 特定状态**的强制规则: ```csharp namespace BaseGames.Combat { /// /// 显式打断关系配置表。HurtBox 在数值比较前优先查询此表。 /// 用于设计"某 Boss 技能无论玩家霸体多高都必须打断"等特殊场合。 /// [CreateAssetMenu(menuName = "Combat/PoiseOverrideTable")] public class PoiseOverrideTableSO : ScriptableObject { public List entries; public PoiseOverrideResult? Query(string attackSourceId, string targetStateId) { foreach (var e in entries) { bool matchAtk = string.IsNullOrEmpty(e.attackSourceId) || e.attackSourceId == attackSourceId; bool matchTarget = string.IsNullOrEmpty(e.targetStateId) || e.targetStateId == targetStateId; if (matchAtk && matchTarget) return e.alwaysInterrupt ? PoiseOverrideResult.AlwaysInterrupt : PoiseOverrideResult.NeverInterrupt; } return null; // 无显式规则,走默认数值逻辑 } } [Serializable] public class PoiseOverrideEntry { [Tooltip("攻击来源 ID(DamageSourceSO.sourceId 或 skillId)。留空 = 匹配所有攻击来源。")] public string attackSourceId; [Tooltip("被打断状态 ID(PlayerStateBase.StateId 或 BossSkillSO.skillId)。留空 = 匹配所有状态。")] public string targetStateId; [Tooltip("true = 强制打断(无视目标霸体等级,Unbreakable 除外)")] public bool alwaysInterrupt; [Tooltip("true = 永不打断(无视打断等级,受击仅扣血)")] public bool neverInterrupt; [TextArea(1, 2)] [Tooltip("记录此规则的设计原因")] public string designNote; } public enum PoiseOverrideResult { AlwaysInterrupt, NeverInterrupt } } ``` **资产存放**:`Assets/ScriptableObjects/Combat/PoiseOverrideTable.asset` **配置示例**: ``` // 规则 1: Boss"虚空起源"的阶段2核心技能"星陨重压"强制打断玩家地行术(即使地行术是 Unbreakable) attackSourceId = "VoidOrigin_StarCrash" targetStateId = "GroundDiveState" alwaysInterrupt = true ← 注意:此处会覆盖 Unbreakable(慎用) designNote = "设计意图:玩家不能通过地行术无伤躲过阶段技" // 规则 2: 玩家弹反成功后的反击(ParryCounter)永不被任何敌人打断 attackSourceId = "" // 空 = 所有攻击来源 targetStateId = "ParryCounterState" neverInterrupt = true designNote = "弹反反击动作不应被打断,维护弹反奖励感" // 规则 3: 精英敌人"石甲虫"的普通攻击对玩家施放天魂所有技能均无法打断 attackSourceId = "StoneArmadillo_Attack" targetStateId = "" // 空 = 所有玩家状态 neverInterrupt = true designNote = "石甲虫攻击较弱,不应打断任何玩家行动" ``` --- ## 10. 全动作霸体参考表 ### 玩家攻击打断等级 | 动作 | 天魂 BreakLevel | 地魂 BreakLevel | 命魂 BreakLevel | |------|:-----------:|:-----------:|:-----------:| | Attack1 | Light | Medium | Light | | Attack2 | Light | Medium | Light | | Attack3 | Medium | Heavy | Medium | | AirAttack | Light | Medium | Light | | UpAttack | Light | Medium | Light | | DownAttack(Pogo)| Light | Medium | Light | | ParryCounter | Heavy | Heavy | Heavy | > 地魂武器整体打断等级高一级,体现"重击"特性。 ### 玩家技能打断等级 | 技能 | BreakLevel | 说明 | |------|:----------:|------| | 裂空掌 | Heavy | 近战 AoE,高打断 | | 漩灵击 | Medium | 护体,打断中等 | | 灵踪弹 | Light | 弹射物,轻打断 | | 地行术 | None | 入地,无接触打断 | | 霸山拳 | Breaker | 破甲重拳 | | 魂元爆 | Medium | 爆炸,中等打断 | | 登龙蹴 | Heavy | 升龙,高打断 | | 太虚斩 | Medium | 冲刺斩,中打断 | | 残阴术(残影攻击)| Light | 残影,轻打断 | ### 能力状态打断等级(玩家被击时视角) (参见 §7.3 能力状态霸体表) --- ## 11. 平衡设计准则 ### 玩家侧 1. **普通连击段(Attack1/2)** 一般不给霸体,保持高风险高收益的近身博弈感 2. **第三段(Attack3)** 给 `Light` 或 `Medium` 霸体,奖励打完完整连击的玩家 3. **重要技能施放**(霸山拳、登龙蹴)给 `Medium`–`Heavy` 霸体,让技能"值得放" 4. **灵泉治疗** 给 `Heavy` 霸体,保证玩家有机会用完一个治疗不被打断 5. **冲刺** 使用 IFrame 而非霸体(短距离无敌,不受霸体系统管辖) ### 敌人侧 1. **普通敌人攻击** BreakLevel 统一为 `Light`(只能打断无霸体动作) 2. **精英怪攻击** BreakLevel 可到 `Medium`(能打断玩家轻霸体) 3. **Boss 核心技能** BreakLevel 可到 `Heavy` 或 `Breaker`(压制玩家大部分动作) 4. **Boss 蓄力/前摇** poiseWindow 给 `Heavy`,让玩家意识到"这招不能被随意取消" ### 禁止事项 | 禁止 | 原因 | |------|------| | 给 `Unbreakable` 的攻击设置 `PoiseOverrideEntry.alwaysInterrupt` | 会破坏设计安全感,须经负责人审核 | | 玩家普通攻击 BreakLevel ≥ Heavy | 普通攻击打断 Boss 重霸体会让 Boss 失去压迫感 | | BreakLevel = Breaker 的弹射物 | 远程破甲会使近战霸体设计失去意义 | --- ## 12. 编辑器友好设计 ### HurtBox Gizmo 可视化 运行时暂停时,HurtBox 的 Gizmo 显示: ``` 受击对象: Player 当前状态: AttackState (Attack3) 当前霸体: Medium [窗口 0.0 ~ 1.0 全程] 最近受击: DS_Boss_Charge (BreakLevel: Heavy) 打断结果: ✅ Interrupted (Heavy >= Medium) ``` ### PoiseOverrideTable 编辑器窗口 `Tools → Zeling → Poise Override Table`: ``` ┌─ Poise Override Table ─────────────────────────────────────┐ │ [自动验证:检查 attackSourceId / targetStateId 是否存在] │ │ │ │ # | 攻击来源 | 目标状态 | 类型 │ │ 1 | VoidOrigin_Star | GroundDiveState | AlwaysBreak │ │ 2 | (全部) | ParryCounterState | NeverBreak │ │ ... │ │ [+ 添加规则] [导出 CSV] [验证全部] │ └────────────────────────────────────────────────────────────┘ ``` 自动验证会检查: - `attackSourceId` 对应的 `DamageSourceSO` / `FormSkillSO` / `BossSkillSO` 是否存在 - `targetStateId` 对应的 `PlayerStateBase` 子类或 `BossSkillSO.skillId` 是否存在 - 是否同时勾选 `alwaysInterrupt` 和 `neverInterrupt`(互斥,报错)