diff --git a/Assets/_Game/Scripts/Player/States/AttackState.cs b/Assets/_Game/Scripts/Player/States/AttackState.cs index c832982..c4a3dc1 100644 --- a/Assets/_Game/Scripts/Player/States/AttackState.cs +++ b/Assets/_Game/Scripts/Player/States/AttackState.cs @@ -171,7 +171,11 @@ namespace BaseGames.Player.States // 已是最后一段:消耗掉多余输入,继续进入等待阶段(不 return) } - // 进入动画后等待阶段 + // 进入动画后等待阶段。 + // 必须播放新动画(Idle),否则 Animancer End Event 会在每帧重复触发 OnClipEnd。 + if (AnimCfg?.Idle != null) + Anim.Play(AnimCfg.Idle); + var step = Owner.Weapon?.ActiveWeapon?.GetGroundStep(_comboIndex) ?? default; float spd = Stats?.AnimatorSpeedMultiplier ?? 1f; float now = Time.time; diff --git a/Docs/Tuning/WeaponSO_Tuning.md b/Docs/Tuning/WeaponSO_Tuning.md new file mode 100644 index 0000000..5be96a6 --- /dev/null +++ b/Docs/Tuning/WeaponSO_Tuning.md @@ -0,0 +1,366 @@ +# WeaponSO 武器调参指南 + +**配置文件**:`Assets/_Game/Data/Combat/Weapons/WPN_*.asset` +**对应脚本**:`WeaponSO.cs` · `ComboStepConfig` · `WeaponVFXConfig` +**创建工具**:Unity 菜单 `BaseGames/Data/Weapon Editor`(勿直接在 Project 窗口创建) +**影响系统**:`WeaponManager` · `WeaponHitBoxInstance` · `PlayerCombat` · `FormController` + +--- + +## 一、架构概述 + +``` +WeaponSO +├── 基础信息(weaponId / displayName / icon / weaponType) +├── groundComboSteps[] ── 地面连击(任意段数) +├── airComboSteps[] ── 空中攻击(通常 1 段) +├── upStep ── 上劈(固定单段) +├── downStep ── 下劈(固定单段) +├── hitBoxPrefab ── 武器 HitBox Prefab(含 WeaponHitBoxInstance) +├── vfxConfig ── 特效配置 +└── soulPowerGain ── 命中灵力获取量 + +每段攻击的核心数据由 ComboStepConfig 描述: +ComboStepConfig +├── clip ── Animancer ClipTransition(动画片段) +├── damageSource ── DamageSourceSO(伤害参数) +├── hitBoxEnter/Exit ── HitBox 激活窗口(归一化 0-1) +├── comboInputOpen/Close── 连击接受窗口(归一化 0-1) +├── cancelWindowOpen ── 跳跃/冲刺取消窗口(归一化 0-1) +├── recoveryTime ── 动画结束后硬直(秒) +├── comboTimeout ── 等待下一段连击的超时(秒) +└── hitBoxId ── 指定激活 Prefab 中的具名 HitBox(空=方向默认) +``` + +**WeaponManager** 监听 `FormController.OnFormChanged`,依据当前形态或护符 Override 切换 `ActiveWeapon`,并在 `[WeaponSocket]` 下实例化/池化对应 `hitBoxPrefab`。 + +--- + +## 二、基础信息字段 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `weaponId` | string | 全局唯一 ID,命名规范:`Weapon_<主题名>`,如 `Weapon_SkyBlade`。**必须唯一,运行时依此检索。** | +| `displayName` | string | UI 显示名,如 `天裂刃`。 | +| `icon` | Sprite | HUD / 物品栏图标。 | +| `weaponType` | WeaponType | 枚举,影响动画控制器分支和特殊逻辑:`TianHun`(天魂)/ `DiHun`(地魂)/ `MingHun`(命魂)/ `Custom`。 | + +--- + +## 三、ComboStepConfig 字段详解 + +### 3.1 动画 & 伤害 + +| 字段 | 类型 | 说明 | +|---|---|---| +| `clip` | ClipTransition | Animancer 动画片段引用。在 Inspector 中直接拖入 AnimationClip 资产,Animancer 自动包装为 Transition。 | +| `damageSource` | DamageSourceSO | 本段攻击的伤害数据 SO(详见第五节)。**每段连击可独立配置不同伤害参数**,如首段轻击、末段重击。 | + +### 3.2 HitBox 激活窗口(归一化 0-1) + +> 所有归一化时间均相对于该段动画片段的**总时长**。0 = 动画开始,1 = 动画结束。 + +| 字段 | 范围 | 说明 | +|---|---|---| +| `hitBoxEnter` | [0, 1] | HitBox Collider2D 开启时间点。过早会导致判定在动作启动前已生效(容易打中玩家不期待的时机)。 | +| `hitBoxExit` | [0, 1] | HitBox Collider2D 关闭时间点。`hitBoxExit > hitBoxEnter`,差值越大判定活跃窗口越长。 | + +**经验准则**: +- 轻击:窗口宽度约 `0.25-0.35`(如 `Enter=0.25, Exit=0.55`) +- 重击:窗口宽度约 `0.35-0.55`(动作前摇长,Enter 较晚) +- 判定窗口开始前应能看到挥砍动作的启动帧,避免"隐形打击" + +### 3.3 连击输入窗口(归一化 0-1) + +| 字段 | 范围 | 说明 | +|---|---|---| +| `comboInputOpen` | [0, 1] | 从此时间点起**开始接受**下一段连击输入。设为 `0` = 动画一开始就可以缓冲输入。 | +| `comboInputClose` | [0, 1] | 从此时间点起**停止接受**连击输入(必须在 `comboInputOpen` 之后)。设为 `0` = 持续到动画结束。 | + +**经验准则**: +- `comboInputOpen` 建议设在 HitBox 激活之后(让玩家确认打中后才能输入连击) +- 对于高速连击,`comboInputOpen = 0`(从头缓冲)可提升流畅感 +- `comboInputClose = 0`(持续到动画结束)是最宽松的设定,适合友好手感 + +### 3.4 取消窗口(归一化 0-1) + +| 字段 | 范围 | 说明 | +|---|---|---| +| `cancelWindowOpen` | [0, 1] | 从此时间点起**允许跳跃/冲刺打断**本段攻击。设为 `0` = 仅在动画结束后的恢复期内允许取消。 | + +**经验准则**: +- 过早打开(如 `0.2`)会让攻击感觉"没有重量",玩家容易意外取消 +- 推荐在动画进入收招阶段时开放,约 `0.5-0.6` +- 下劈攻击(Pogo 跳)通常设得较早(`0.3`),便于空中快速接跳 + +### 3.5 时间参数(秒,受攻速倍率缩放) + +| 字段 | 最小值 | 说明 | +|---|---|---| +| `recoveryTime` | 0 | 动画结束后的**硬直时间**(秒),期间跳跃/冲刺无法打断。模拟挥空后的惯性/踉跄。 | +| `comboTimeout` | 0 | 硬直结束后**等待连击输入的时间**(秒)。超时则返回 Idle 状态。设为 `0` = 立即返回 Idle。 | + +> ⚠️ 这两个参数受攻速倍率缩放。`recoveryTime = 0.05f` 是默认最低有效值,不建议设 `0`(否则帧序列可能出现单帧状态切换问题)。 + +### 3.6 HitBox 绑定 ID + +| 字段 | 说明 | +|---|---| +| `hitBoxId` | 留空 → 使用该方向的**默认 HitBox**(WeaponHitBoxInstance 中对应方向的字段);
非空 → **按 Id 精确激活** Prefab 中对应子节点的 HitBox,可为每段连击配置不同的判定形状。 | + +**使用时机**: +- 连击首段和末段的判定范围不同时(如末段范围更大) +- 需要多个独立判定区域时(如武器特殊技能) + +--- + +## 四、DamageSourceSO 关键参数 + +每个 `ComboStepConfig.damageSource` 引用一个独立的 `DamageSourceSO` 资产,资产命名规范:`CMB_DmgSrc_<武器ID>_<段序号>.asset`,存放于 `_Game/Data/Combat/DamageSources/`。 + +| 字段 | 默认值 | 说明 | +|---|---|---| +| `BaseDamage` | 10 | 本段攻击基础伤害值(整型)。 | +| `DamageMultiplier` | 1.0 | 倍率,最终伤害 = `Round(BaseDamage × DamageMultiplier)`。 | +| `Type` | Normal | 伤害元素类型(`Normal` / `Fire` / `Poison` / `Ice` / `Lightning` / `Void` / `True`)。`True` = 无视防御的真实伤害。 | +| `Category` | NormalAttack | 来源分类,影响护符/技能的条件判断(如"普通攻击命中时触发")。 | +| `Flags` | CanBeParried | 行为标志(可组合)。常见组合见下表。 | +| `Tags` | MeleeHit | 交互标签(可组合),配合 DamageTags 枚举使用。 | +| `KnockbackForce` | 5.0 | 击退力度(单位/秒,直接施加速度)。 | +| `HitStunDuration` | 0.1 | 击中后的受击硬直时间(秒)。 | +| `BreakLevel` | Light | 攻击方打断等级,与敌人 `PoiseLevel` 比较决定是否打断霸体。 | +| `FxType` | Slash | 命中特效类型,决定播放哪套打击感反馈预设。 | + +**DamageFlags 常用组合**: + +| 组合 | 适用场景 | +|---|---| +| `CanBeParried` | 普通攻击(可被格挡) | +| `CanBeParried \| CanClash` | 可碰撞武器(弹反对碰) | +| `Unblockable` | 突破技/破防攻击 | +| `CanBeParried \| PerfectParryOnly` | 高危攻击,仅完美格挡才能弹反 | +| `NoKnockback` | 固定伤害(毒、灼烧等 DoT 不需要击退) | + +--- + +## 五、WeaponVFXConfig 字段 + +| 字段 | 说明 | +|---|---| +| `onEquipPresetId` | 切换到此武器时播放的特效预设 ID,对应 `IFeedbackPlayer.TriggerPreset`。空 = 不播放切换特效。 | +| `weaponTrailPrefab` | 挥斩拖尾 Prefab(null = 不显示拖尾)。拖尾 Prefab 应含 `TrailRenderer` 或自定义拖尾脚本。 | +| `trailColor` | 拖尾颜色,可在 Inspector 中用 HDR 色板设定发光颜色。默认白色。 | + +--- + +## 六、战斗参数 + +| 字段 | 默认值 | 说明 | +|---|---|---| +| `soulPowerGain` | 10 | **命中确认时增加的灵力值**,覆盖 PlayerCombat 全局默认值(也为 10)。可对强力武器设更高值(如 DiHun 重击设 15-20),鼓励玩家积极进攻。 | + +--- + +## 七、推荐配置 + +### 7.1 时间轴可视化参考 + +以下图示展示一段典型地面连击的时间轴布局(归一化 0-1): + +``` +0 ────────────────────────────────────── 1 (动画片段) + │←── HitBox 激活窗口 ──→│ + hitBoxEnter(0.25) hitBoxExit(0.60) + + │←── 连击输入开放 ─────────────────────→│ + comboInputOpen(0.20) comboInputClose(0=持续到结束) + + │← 取消窗口(可跳/冲) →│ + cancelWindowOpen(0.50) + +完整时间轴: +[动画] ────────────────────────── [recoveryTime] [comboTimeout] + |←─ 0.05s ──→||←── 0.25s ──→| +``` + +### 7.2 天魂 TianHun(高频轻击,如天裂刃) + +> 定位:高频连击,4 段地面 + 1 段空中,每段伤害低但命中频繁,玩家可快速积累灵力。 + +#### 地面连击(4 段) + +| 参数 | 第 1 段 | 第 2 段 | 第 3 段 | 第 4 段(末段) | +|---|---|---|---|---| +| `hitBoxEnter` | 0.25 | 0.20 | 0.20 | 0.30 | +| `hitBoxExit` | 0.55 | 0.50 | 0.55 | 0.70 | +| `comboInputOpen` | 0.20 | 0.15 | 0.15 | 0 | +| `comboInputClose` | 0 | 0 | 0 | 0 | +| `cancelWindowOpen` | 0.55 | 0.50 | 0.50 | 0.60 | +| `recoveryTime` | 0.05 | 0.05 | 0.05 | 0.08 | +| `comboTimeout` | 0.20 | 0.20 | 0.20 | 0.15 | + +#### 空中攻击(1 段) + +| 参数 | 推荐值 | +|---|---| +| `hitBoxEnter` | 0.10 | +| `hitBoxExit` | 0.70 | +| `comboInputOpen` | 0 | +| `cancelWindowOpen` | 0.40 | +| `recoveryTime` | 0.05 | + +#### 上劈 / 下劈 + +| 参数 | 上劈 | 下劈 | +|---|---|---| +| `hitBoxEnter` | 0.20 | 0.10 | +| `hitBoxExit` | 0.65 | 0.85 | +| `cancelWindowOpen` | 0.55 | 0.30(早开放,便于 Pogo) | +| `recoveryTime` | 0.05 | 0.05 | + +#### DamageSource 参数(天魂各段参考) + +| 参数 | 第 1-3 段 | 第 4 段(末段) | +|---|---|---| +| `BaseDamage` | 8 | 12 | +| `DamageMultiplier` | 1.0 | 1.2 | +| `KnockbackForce` | 3.0 | 5.0 | +| `HitStunDuration` | 0.08 | 0.12 | +| `BreakLevel` | Light | Medium | +| `FxType` | Slash | Slash | +| `Flags` | CanBeParried | CanBeParried | + +**soulPowerGain**:`10`(每段命中均为标准值,高频命中本身已能快速积累) + +--- + +### 7.3 地魂 DiHun(低频重击,如地震锤) + +> 定位:2 段地面,前摇长、打击感强,单段伤害高,击退效果明显,适合破霸体。 + +#### 地面连击(2 段) + +| 参数 | 第 1 段 | 第 2 段(蓄力重击) | +|---|---|---| +| `hitBoxEnter` | 0.40 | 0.50 | +| `hitBoxExit` | 0.70 | 0.85 | +| `comboInputOpen` | 0.35 | 0 | +| `comboInputClose` | 0 | 0 | +| `cancelWindowOpen` | 0.65 | 0.70 | +| `recoveryTime` | 0.12 | 0.20 | +| `comboTimeout` | 0.30 | 0.20 | + +#### 空中攻击(1 段,范围攻击) + +| 参数 | 推荐值 | +|---|---| +| `hitBoxEnter` | 0.20 | +| `hitBoxExit` | 0.80 | +| `cancelWindowOpen` | 0.60 | +| `recoveryTime` | 0.10 | + +#### DamageSource 参数(地魂各段参考) + +| 参数 | 第 1 段 | 第 2 段 | +|---|---|---| +| `BaseDamage` | 18 | 28 | +| `DamageMultiplier` | 1.0 | 1.3 | +| `KnockbackForce` | 7.0 | 12.0 | +| `HitStunDuration` | 0.15 | 0.25 | +| `BreakLevel` | Medium | Heavy | +| `FxType` | Heavy | Heavy | +| `Flags` | CanBeParried \| CanClash | CanBeParried \| CanClash | + +**soulPowerGain**:`18`(重击命中奖励更多灵力,鼓励玩家进行高风险的大招命中) + +--- + +### 7.4 命魂 MingHun(穿透直线斩,命镰) + +> 定位:3 段地面,带穿透 Tag,直线攻击范围长,无强力击退,适合多目标清线。 + +#### 地面连击(3 段) + +| 参数 | 第 1 段 | 第 2 段 | 第 3 段(穿透斩) | +|---|---|---|---| +| `hitBoxEnter` | 0.20 | 0.20 | 0.25 | +| `hitBoxExit` | 0.55 | 0.55 | 0.75 | +| `comboInputOpen` | 0.20 | 0.20 | 0 | +| `comboInputClose` | 0 | 0 | 0 | +| `cancelWindowOpen` | 0.50 | 0.50 | 0.60 | +| `recoveryTime` | 0.06 | 0.06 | 0.10 | +| `comboTimeout` | 0.25 | 0.25 | 0.20 | + +#### DamageSource 参数(命魂各段参考) + +| 参数 | 第 1-2 段 | 第 3 段(穿透) | +|---|---|---| +| `BaseDamage` | 10 | 16 | +| `DamageMultiplier` | 1.0 | 1.1 | +| `KnockbackForce` | 2.0 | 3.0 | +| `HitStunDuration` | 0.10 | 0.12 | +| `BreakLevel` | Light | Light | +| `FxType` | Slash | Void | +| `Flags` | CanBeParried | CanBeParried | +| `Tags` | MeleeHit | MeleeHit \| DeathFormOnly | + +**soulPowerGain**:`12`(中等收益,穿透多目标时单次激活返回较多灵力) + +--- + +## 八、三武器横向对比 + +| 属性 | TianHun(天魂) | DiHun(地魂) | MingHun(命魂) | +|---|---|---|---| +| 连击段数 | 4 段 | 2 段 | 3 段 | +| 单段基础伤害 | 8-12 | 18-28 | 10-16 | +| 击退力度 | 低(3-5) | 高(7-12) | 极低(2-3) | +| HitStun | 短(0.08-0.12s) | 长(0.15-0.25s) | 中(0.10-0.12s) | +| BreakLevel | Light → Medium | Medium → Heavy | Light | +| HitBox 窗口宽度 | 窄(~0.30) | 宽(~0.35) | 中(~0.35-0.50) | +| recoveryTime 末段 | 0.08s | 0.20s | 0.10s | +| soulPowerGain | 10 | 18 | 12 | +| 特色 | 高频灵力积累 | 破霸体/强力击退 | 穿透多目标 | + +--- + +## 九、HitBox Prefab 配置要点 + +命名规范:`WPN_{weaponId}_HitBox.prefab`,存放于 `Assets/_Game/Prefabs/Weapons/` + +``` +[WPN_SkyBlade_HitBox] ← WeaponHitBoxInstance 脚本 +├── [HitBox_Ground] Id="" ← 方向默认(Inspector 引用到 _hitBoxGround) +├── [HitBox_Ground_3] Id="g3" ← 第 3 段专属判定(更大范围) +├── [HitBox_Up] Id="" ← 上劈默认(Inspector 引用到 _hitBoxUp) +├── [HitBox_Down] Id="" ← 下劈默认(Inspector 引用到 _hitBoxDown) +└── [HitBox_Air] Id="" ← 空中默认(Inspector 引用到 _hitBoxAir) +``` + +- **不要**在 HitBox Prefab 上挂 Rigidbody2D(由父节点 Player 提供物理) +- Collider2D 默认 **disabled**,由 `HitBox.Activate()` 开启 +- 多段攻击需要不同判定形状时,添加具名子节点,在对应 `ComboStepConfig.hitBoxId` 中填写对应 Id + +--- + +## 十、常见调参问题排查 + +| 现象 | 可能原因 | 排查方向 | +|---|---|---| +| 攻击时判定出现太早,感觉"不对" | `hitBoxEnter` 过小 | 调高至 0.25-0.35,与动画挥砍帧对齐 | +| 连击无法触发,只能打第 1 段 | `comboInputOpen` 太晚或 `comboInputClose` 太早 | 调低 `comboInputOpen`(或设 0),确认 `comboInputClose` 为 0 | +| 攻击后无法立即跳跃/冲刺 | `cancelWindowOpen` 过大或 `recoveryTime` 过长 | 降低 `cancelWindowOpen`(0.50-0.55),减小 `recoveryTime` | +| 末段后角色卡顿太久才能动 | `recoveryTime` + `comboTimeout` 总计过长 | 减小其中一个或两者都减小 | +| HitBox 命中范围与动画不匹配 | HitBox Prefab 中 Collider2D 形状未对齐 | 在 Scene 视图的 Gizmos 开启后,逐帧检查碰撞体位置 | +| 连击结束后立刻返回 Idle,没有残影感 | `comboTimeout = 0` | 设为 `0.15-0.25s`,让玩家有余裕进行下一段连击 | +| 重击前摇太短,没有"蓄力感" | `hitBoxEnter` 过小(前摇太短就进入判定) | 调高至 0.40-0.55,延长前摇 | +| 空中攻击结束后角色位移异常 | HitBox 取消窗口过早,冲刺接入空攻状态 | 调高 `cancelWindowOpen`(≥ 0.50)或检查状态机过渡条件 | +| 命中无灵力回复 | `damageSource` 引用为空,或 `soulPowerGain = 0` | 检查每个 ComboStepConfig 的 `damageSource` 字段不为 null | + +--- + +## 十一、修改历史 + +| 日期 | 修改内容 | +|---|---| +| 2026-05-22 | 初版:覆盖 WeaponSO 全部字段说明、三武器推荐配置及调参排查表 |