fix(enemy): Waypoint 巡逻寻路失败/丢失时自动重发,修复出生即巡逻卡死

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) <noreply@anthropic.com>
This commit is contained in:
2026-07-23 15:13:19 +08:00
co-authored by Claude Opus 4.8
parent be7d511e45
commit 16edf7cb90
@@ -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;
}
}