refactor(enemy): 三处卡死检测收敛为 StallDetector;修复 Pace 持续受阻时无法掉头的死锁
This commit is contained in:
@@ -33,8 +33,8 @@ namespace BaseGames.Enemies
|
||||
private bool _gaitInit;
|
||||
private float _paceDir = 1f;
|
||||
private bool _paceBlockedPrev;
|
||||
private float _paceWindowStartX;
|
||||
private int _paceWindowFrames;
|
||||
// Pace 推进停滞检测(原为 12 帧计数,@60fps ≈ 0.2s,改用统一原语并保持观感)
|
||||
private StallDetector _paceStall = new StallDetector(0.2f, 0.05f);
|
||||
private int _wpIndex = -1;
|
||||
private int _wpDir = 1;
|
||||
private bool _warnedNoWaypoints;
|
||||
@@ -179,22 +179,17 @@ namespace BaseGames.Enemies
|
||||
// 用与移动层夹紧同一判定(WouldBlockAhead,即时按请求方向+碰撞体前缘),
|
||||
// 保证"夹停在地形边缘"与"掉头"一致,不会夹停却不翻向。
|
||||
bool blocked = mv != null && mv.WouldBlockAhead(_paceDir);
|
||||
// 兜底卡死检测(窗口净位移):命令前进但一段时间净位移过小(撞上未挂检测层的墙/
|
||||
// 卡角,含贴墙微抖)也视为受阻,使巡逻对场景配置鲁棒。用净位移而非逐帧差,
|
||||
// 避免"贴墙推进-被弹回"的微抖每帧重置计数。
|
||||
float px = _enemy.transform.position.x;
|
||||
if (++_paceWindowFrames >= 12)
|
||||
{
|
||||
if (Mathf.Abs(px - _paceWindowStartX) < 0.05f) blocked = true;
|
||||
_paceWindowStartX = px;
|
||||
_paceWindowFrames = 0;
|
||||
}
|
||||
// 边沿触发:仅"障碍首次出现"翻一次;翻后按新方向即时判定,天然消抖,
|
||||
// 且两侧都堵(窄台)时翻一次即停住、不来回抖。
|
||||
if (blocked && !_paceBlockedPrev)
|
||||
// 兜底卡死检测:命令前进但窗口内净位移过小(撞上未挂检测层的墙/卡角,含贴墙微抖)也视为受阻。
|
||||
if (_paceStall.Tick(_enemy.transform.position.x, Time.deltaTime)) blocked = true;
|
||||
|
||||
// 翻向:首次受阻翻一次(边沿触发,天然消抖);或"持续受阻但反方向畅通"也翻——
|
||||
// 后者修复"顶着堵侧却因边沿触发失效而永远转不回来"的死锁。
|
||||
// 两侧都堵(窄台)时只有边沿那一次翻向,之后保持,不来回抖。
|
||||
bool oppositeFree = mv != null && !mv.WouldBlockAhead(-_paceDir);
|
||||
if (blocked && (!_paceBlockedPrev || oppositeFree))
|
||||
{
|
||||
_paceDir = -_paceDir;
|
||||
_paceWindowStartX = px; _paceWindowFrames = 0; // 翻向后重开窗口
|
||||
_paceStall.Reset(_enemy.transform.position.x); // 翻向后重开窗口
|
||||
}
|
||||
_paceBlockedPrev = blocked;
|
||||
_enemy.MoveInDirection(_paceDir);
|
||||
|
||||
Reference in New Issue
Block a user