refactor(enemy): 三处卡死检测收敛为 StallDetector;修复 Pace 持续受阻时无法掉头的死锁
This commit is contained in:
@@ -91,9 +91,7 @@ namespace BaseGames.Enemies.Navigation
|
||||
private bool _redirectedToClosest; // 本轮已改道到最近点,避免每帧重复下发
|
||||
private bool _obstructionSignal; // 受阻信号(寻路失败/卡死),延后到 FixedUpdate 统一处理
|
||||
// 卡死检测窗口
|
||||
private float _stuckWinTimer;
|
||||
private float _stuckWinStartDist;
|
||||
private bool _stuckWinInit;
|
||||
private StallDetector _segStall;
|
||||
|
||||
// 连接段状态缓存
|
||||
private NavLinkType _currentLinkType = NavLinkType.None;
|
||||
@@ -121,6 +119,8 @@ namespace BaseGames.Enemies.Navigation
|
||||
_navAgent.OnSegmentTraversal += HandleSegmentTraversal;
|
||||
_navAgent.OnFailedToFindPath += HandlePathFailed;
|
||||
_navAgent.OnReachedGoal += HandleGoalReached;
|
||||
|
||||
_segStall = new StallDetector(_stuckWindowSeconds, _stuckMinProgress);
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
@@ -327,30 +327,16 @@ namespace BaseGames.Enemies.Navigation
|
||||
_wasNavOnSegment = onSegment;
|
||||
}
|
||||
|
||||
// 卡死检测:段上移动时,滑动窗口内朝子目标推进不足阈值 → 判受阻(覆盖"障碍未进图"的物理空推)。
|
||||
// 卡死检测:段上移动时,窗口内净水平位移不足 → 判受阻(覆盖"障碍未进图"的物理空推)。
|
||||
// 原实现比较"到子目标的距离缩小量",现统一为净水平位移:不依赖子目标,且绕行时不会误判为卡死。
|
||||
private void TickStuckDetection(bool onSegment)
|
||||
{
|
||||
if (!onSegment) { _stuckWinInit = false; return; }
|
||||
|
||||
float dist = Mathf.Abs(_navAgent.PathSubGoal.x - transform.position.x);
|
||||
if (!_stuckWinInit)
|
||||
{
|
||||
_stuckWinInit = true;
|
||||
_stuckWinTimer = 0f;
|
||||
_stuckWinStartDist = dist;
|
||||
return;
|
||||
}
|
||||
_stuckWinTimer += Time.fixedDeltaTime;
|
||||
if (_stuckWinTimer >= _stuckWindowSeconds)
|
||||
{
|
||||
if (_stuckWinStartDist - dist < _stuckMinProgress)
|
||||
_obstructionSignal = true; // 窗口内几乎没靠近子目标 → 卡死
|
||||
_stuckWinTimer = 0f;
|
||||
_stuckWinStartDist = dist;
|
||||
}
|
||||
if (!onSegment) { _segStall.Reset(transform.position.x); return; }
|
||||
if (_segStall.Tick(transform.position.x, Time.fixedDeltaTime))
|
||||
_obstructionSignal = true; // 窗口内几乎没推进 → 卡死
|
||||
}
|
||||
|
||||
private void ResetStuckWindow() => _stuckWinInit = false;
|
||||
private void ResetStuckWindow() => _segStall.Reset(transform.position.x);
|
||||
|
||||
// 统一受阻处理:尽力改道到最近可达点(走到障碍前),拿不到更近点则停下,交由意图层结算。
|
||||
private void ProcessObstruction()
|
||||
|
||||
Reference in New Issue
Block a user