From 16edf7cb902252904b5caac6f9c854d38eba288d Mon Sep 17 00:00:00 2001 From: Joywayer Date: Thu, 23 Jul 2026 15:13:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(enemy):=20Waypoint=20=E5=B7=A1=E9=80=BB?= =?UTF-8?q?=E5=AF=BB=E8=B7=AF=E5=A4=B1=E8=B4=A5/=E4=B8=A2=E5=A4=B1?= =?UTF-8?q?=E6=97=B6=E8=87=AA=E5=8A=A8=E9=87=8D=E5=8F=91,=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=87=BA=E7=94=9F=E5=8D=B3=E5=B7=A1=E9=80=BB=E5=8D=A1?= =?UTF-8?q?=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TickPatrol 原来只在"首次或到达路点"时发一次 MoveTo。若这一次 UpdatePath 失败(如敌人 刚出生、当帧尚未映射到 NavGraph),路径永不建立且再不重试 → 永久原地不动(mode=Patrol 但 IsFollowingAPath=False)。旧 Entry=Idle_Disguise 因巡逻只在出生很久后才开始而掩盖了此问题。 新增:有目标但 nav 空闲(!IsMoving)且未到达 → 重发同一目标(只重发不推进索引;RequestMoveTo 自带 0.25s 防抖,寻路跨帧计算期间的重发被吞掉,不会每帧重启寻路)。 Play 实测:出生即在两路点间以 WalkSpeed 正常往返巡逻。 Co-Authored-By: Claude Opus 4.8 (1M context) --- .../Scripts/Enemies/Navigation/EnemyLocomotion.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs b/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs index 0b7e4d30..aedaca57 100644 --- a/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs +++ b/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs @@ -194,16 +194,23 @@ namespace BaseGames.Enemies } break; } - // 仅首次或"已到达当前路点"时推进并寻路——不依赖 IsMoving - // (PathBerserker2d 寻路跨帧异步,IsMoving 在寻路计算期间为 false,会误触发每帧推进)。 // 到达判定对"吸附后的可达点"做,而非原始路点:原始路点可能摆在空中/崖外, // 与之的距离永远进不了到达半径 → 卡死;吸附点是身体站得住的可达点。 - if (_wpIndex < 0 || - Vector2.Distance(_enemy.transform.position, _wpResolvedGoal) <= _waypointArriveRadius) + bool wpArrived = _wpIndex >= 0 && + Vector2.Distance(_enemy.transform.position, _wpResolvedGoal) <= _waypointArriveRadius; + if (_wpIndex < 0 || wpArrived) { + // 首次 / 到达当前路点 → 推进到下一路点并寻路 AdvanceWaypoint(); SetWaypointGoal(); } + else if (_enemy.Nav != null && !_enemy.Nav.IsMoving) + { + // 有目标但 nav 空闲且未到达:初始寻路未成(如刚出生、尚未映射到导航图那一帧发的 MoveTo 失败) + // 或路径中途丢失 → 重发同一目标恢复。只重发、不推进索引;RequestMoveTo 自带 0.25s 防抖, + // 寻路跨帧计算期间的重发会被防抖吞掉,不会每帧重启寻路。 + _enemy.MoveTo(_wpResolvedGoal); + } break; } }