From 9eca69a6ba982c7d0fa3d752449d371d84eaa90a Mon Sep 17 00:00:00 2001 From: Joywayer Date: Fri, 10 Jul 2026 16:46:37 +0800 Subject: [PATCH] =?UTF-8?q?@=20feat(enemy):=20E001=20=E8=BF=BD=E5=87=BB?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=86=B2=E5=88=BA+=E5=86=B7=E5=8D=B4(?= =?UTF-8?q?=E6=9C=9D=E7=8E=A9=E5=AE=B6=E6=96=B9=E5=90=91=E5=86=B2=EF=BC=8C?= =?UTF-8?q?=E6=92=9E=E5=A2=99/=E8=BE=B9=E7=BC=98=E5=81=9C=EF=BC=8CCD?= =?UTF-8?q?=E5=90=8E=E5=86=8D=E5=86=B2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按新设计:进入追击→Skill_Start(张口)→起手后按玩家所在侧一次性确定方向→ 速度直冲(非 nav,接触伤害开)→撞墙/到平台边缘(WouldBlockAhead)或受阻即停→ Skill_End(收招)→进入冷却(ABL_E001_Chase.cooldown=1s)。一次冲刺=一次能力执行, AI 追击态在冷却结束时经 EnsureAbility 重触发下一次冲刺。 - ContactChaseAbility:无限跟随改为有限冲刺;方向 committed(会越过跳开的玩家, 可被躲);加窗口净位移卡死兜底——撞上未在检测层的碰撞体(玩家/边界墙)原地不动 时结束冲刺转收招+冷却,避免卡死。 - ABL_E001_Chase.cooldown 0→1(可在 SO 调)。 PlayMode 验证(净域重载后):Skill_Start→冲刺(实测冲 7 单位、伤害开)→受阻→ Skill_End→冷却→冷却结束重新起手冲刺,完整循环。速度直冲不依赖 nav,敌人实际 位移正常。 Co-Authored-By: Claude Opus 4.8 (1M context) @ --- .../E001/Abilities/ABL_E001_Chase.asset | 2 +- .../Enemies/Abilities/ContactChaseAbility.cs | 41 ++++++++++++++----- 2 files changed, 31 insertions(+), 12 deletions(-) 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();