diff --git a/Assets/_Game/Data/Enemies/E001/Abilities/ABL_E001_Chase.asset b/Assets/_Game/Data/Enemies/E001/Abilities/ABL_E001_Chase.asset index 91857c80..2ecb16aa 100644 --- a/Assets/_Game/Data/Enemies/E001/Abilities/ABL_E001_Chase.asset +++ b/Assets/_Game/Data/Enemies/E001/Abilities/ABL_E001_Chase.asset @@ -14,7 +14,7 @@ MonoBehaviour: m_EditorClassIdentifier: abilityId: e001_chase attackSequence: [] - cooldown: 0 + cooldown: 1 telegraphVfxKey: telegraphDuration: 0 interruptOnHurt: 1 diff --git a/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs b/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs index edba583e..4c08f062 100644 --- a/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs +++ b/Assets/_Game/Scripts/Enemies/Abilities/ContactChaseAbility.cs @@ -5,10 +5,11 @@ using UnityEngine; namespace BaseGames.Enemies.Abilities { /// - /// 追击 + 体接触伤害能力:起手(Skill_Start 张口) → 循环追击(Skill_Loop 快速爬行 + 接触伤害) - /// → 收招(Skill_End)。追击动画由本能力全权驱动(Approach 模式不驱动步态,避免抢动画)。 - /// 何时停止由 AI 决策层负责:AI 在"脱离感知"时中断本能力(ExternalRequest),本能力播 Skill_End 收招。 - /// 依据 Docs/Game/Design/小怪设计-程序开发文档-01.md(E001 状态机 Skill_Start/Loop/End)。 + /// 冲刺追击 + 体接触伤害能力:起手(Skill_Start 张口) → 朝玩家方向直冲(Skill_Loop 快速爬行 + + /// 接触伤害),**直到撞墙/到平台边缘或玩家消失即停** → 收招(Skill_End)。一次冲刺为一次能力执行, + /// 结束后进入冷却(EnemyAbilitySO.cooldown);AI 追击态在冷却结束时经 EnsureAbility 重触发下一次冲刺。 + /// 冲刺方向在起手后按玩家所在侧一次性确定(committed 冲锋,会越过跳开的玩家,可被躲)。 + /// 追击动画由本能力全权驱动(Approach 步态不抢动画)。 /// public class ContactChaseAbility : EnemyAbilityBase { @@ -33,20 +34,38 @@ namespace BaseGames.Enemies.Abilities yield return EnemyAbilityWaits.Get(_startClip.Clip.length); } - // 循环追击:切追击速度、开接触伤害、朝玩家移动,播 Skill_Loop(Approach 模式不抢步态)。 - if (_enemy.Nav != null && _enemy.Stats != null) - _enemy.Nav.SetSpeed(_enemy.Stats.RunSpeed); + // 冲刺方向:起手后按玩家所在侧一次性确定(committed 冲锋) + float dir = (_enemy.PlayerTransform != null && + _enemy.PlayerTransform.position.x < _enemy.transform.position.x) ? -1f : 1f; + float speed = _enemy.Stats != null ? _enemy.Stats.RunSpeed : 0f; + var mv = _enemy.Movement; + + // 冲刺:朝该方向直冲、接触伤害开、播 Skill_Loop,直到撞墙/到边缘或玩家消失即停。 if (_loopClip.Clip != null) _animancer.Play(_loopClip); if (_contactDamage != null) _contactDamage.enabled = true; - // 追击直到玩家消失或被 AI 中断(退出追击的决策归 AI)。小怪走 nav 寻路。 - _enemy.Locomotion?.Approach(_enemy.PlayerTransform); - while (_enemy.PlayerTransform != null) + float winX = _enemy.transform.position.x; + float winT = 0f; + while (_enemy.PlayerTransform != null && !(mv != null && mv.WouldBlockAhead(dir))) + { + _enemy.MoveInDirectionWithSpeed(dir, speed); // 速度直冲(非 nav),MoveWithSpeed 悬崖夹紧兜底 yield return null; - // 玩家对象消失(正常收尾):收招 Skill_End。 + // 兜底:撞上未在检测层的碰撞体(玩家/边界墙)导致原地不动 → 结束本次冲刺(转收招+冷却)。 + // 用窗口净位移判定,避免"贴住微抖"每帧重置。 + winT += Time.deltaTime; + if (winT >= 0.15f) + { + if (Mathf.Abs(_enemy.transform.position.x - winX) < 0.05f) break; + winX = _enemy.transform.position.x; + winT = 0f; + } + } + _enemy.StopMovement(); + + // 收招 Skill_End;随后基类按 EnemyAbilitySO.cooldown 施加冷却。 DisableContact(); yield return PlaySkillEnd(); Cleanup();