feat(enemy): Waypoints 受阻/到达即结算推进,删除对不可达点的无限重发
This commit is contained in:
@@ -44,6 +44,9 @@ namespace BaseGames.Enemies
|
||||
// Wander 到点停顿状态
|
||||
private bool _wanderPausing;
|
||||
private float _wanderPauseTimer;
|
||||
// Waypoints 受阻结算停顿状态
|
||||
private bool _wpPausing;
|
||||
private float _wpPauseTimer;
|
||||
|
||||
public LocomotionMode CurrentMode => _mode;
|
||||
public bool IsMoving => _enemy != null && _enemy.Nav != null && _enemy.Nav.IsMoving;
|
||||
@@ -61,6 +64,7 @@ namespace BaseGames.Enemies
|
||||
if (_mode == mode) return;
|
||||
_mode = mode;
|
||||
_wanderPausing = false; // 切换模式清 Wander 停顿态
|
||||
_wpPausing = false; // 同时清 Waypoints 受阻停顿态
|
||||
if (mode == LocomotionMode.Idle) _enemy?.StopMovement();
|
||||
if (mode == LocomotionMode.Patrol && _enemy?.Stats != null)
|
||||
_enemy.Nav?.SetSpeed(_enemy.Stats.WalkSpeed);
|
||||
@@ -194,21 +198,37 @@ namespace BaseGames.Enemies
|
||||
}
|
||||
break;
|
||||
}
|
||||
// 到达判定对"吸附后的可达点"做,而非原始路点:原始路点可能摆在空中/崖外,
|
||||
// 与之的距离永远进不了到达半径 → 卡死;吸附点是身体站得住的可达点。
|
||||
|
||||
var nav = _enemy.Nav;
|
||||
|
||||
// 到达判定对"吸附后的可达点"做(原始路点可能摆在空中/崖外,永远进不了到达半径)。
|
||||
bool wpArrived = _wpIndex >= 0 &&
|
||||
Vector2.Distance(_enemy.transform.position, _wpResolvedGoal) <= _waypointArriveRadius;
|
||||
if (_wpIndex < 0 || wpArrived)
|
||||
|
||||
// 受阻结算:执行层已把敌人带到最近可达点并停下(或原地停) → 视为本路点完成。
|
||||
bool obstructedSettled = nav != null && nav.LastMoveObstructed && !nav.IsMoving;
|
||||
|
||||
if (_wpIndex < 0 || wpArrived || obstructedSettled)
|
||||
{
|
||||
// 首次 / 到达当前路点 → 推进到下一路点并寻路
|
||||
// 受阻结算走短暂停顿(复用 Wander 停顿参数);正常到达/首个点立即推进。
|
||||
if (obstructedSettled && !_wpPausing)
|
||||
{
|
||||
_wpPausing = true;
|
||||
_wpPauseTimer = Random.Range(_wanderPauseMin, Mathf.Max(_wanderPauseMin, _wanderPauseMax));
|
||||
}
|
||||
if (_wpPausing)
|
||||
{
|
||||
_wpPauseTimer -= Time.deltaTime;
|
||||
if (_wpPauseTimer > 0f) break; // 停顿中,原地待机
|
||||
_wpPausing = false;
|
||||
}
|
||||
AdvanceWaypoint();
|
||||
SetWaypointGoal();
|
||||
}
|
||||
else if (_enemy.Nav != null && !_enemy.Nav.IsMoving)
|
||||
else if (nav != null && !nav.IsMoving && !nav.LastMoveObstructed)
|
||||
{
|
||||
// 有目标但 nav 空闲且未到达:初始寻路未成(如刚出生、尚未映射到导航图那一帧发的 MoveTo 失败)
|
||||
// 或路径中途丢失 → 重发同一目标恢复。只重发、不推进索引;RequestMoveTo 自带 0.25s 防抖,
|
||||
// 寻路跨帧计算期间的重发会被防抖吞掉,不会每帧重启寻路。
|
||||
// 瞬态:刚出生尚未映射那一帧的 MoveTo 失败 → 重发(RequestMoveTo 自带 0.25s 防抖)。
|
||||
// 仅"未受阻"时重发;受阻由上面 obstructedSettled 分支结算,不再无限重发不可达点。
|
||||
_enemy.MoveTo(_wpResolvedGoal);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user