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