57 lines
2.1 KiB
C#
57 lines
2.1 KiB
C#
using UnityEngine;
|
|
|
|
namespace BaseGames.Enemies
|
|
{
|
|
/// <summary>
|
|
/// 推进停滞检测:滑动窗口内的**净水平位移**不足阈值即判为停滞。
|
|
/// 用于"命令了移动却推不动"的兜底(撞上未纳入检测层的碰撞体、贴墙微抖等)。
|
|
///
|
|
/// <para>用净位移而非逐帧差值,避免"贴墙推进-被弹回"的微抖每帧重置计数。</para>
|
|
/// <para><b>调用方须以字段持有本结构</b>(struct 的方法会就地修改字段);
|
|
/// 开始移动 / 更换目标后调用 <see cref="Reset"/> 重开窗口。</para>
|
|
/// </summary>
|
|
public struct StallDetector
|
|
{
|
|
private readonly float _windowSeconds;
|
|
private readonly float _minProgress;
|
|
private float _timer;
|
|
private float _startX;
|
|
private bool _initialized;
|
|
|
|
/// <param name="windowSeconds">判定窗口时长(秒)。</param>
|
|
/// <param name="minProgress">窗口内所需的最小净位移(米)。</param>
|
|
public StallDetector(float windowSeconds, float minProgress)
|
|
{
|
|
_windowSeconds = windowSeconds;
|
|
_minProgress = minProgress;
|
|
_timer = 0f;
|
|
_startX = 0f;
|
|
_initialized = false;
|
|
}
|
|
|
|
/// <summary>以当前位置重开窗口。</summary>
|
|
public void Reset(float currentX)
|
|
{
|
|
_startX = currentX;
|
|
_timer = 0f;
|
|
_initialized = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 推进一帧。返回 true 表示本窗口内推进不足(停滞);返回 true 后窗口自动以当前位置重开。
|
|
/// </summary>
|
|
public bool Tick(float currentX, float deltaTime)
|
|
{
|
|
if (!_initialized) { Reset(currentX); return false; }
|
|
|
|
_timer += deltaTime;
|
|
if (_timer < _windowSeconds) return false;
|
|
|
|
bool stalled = Mathf.Abs(currentX - _startX) < _minProgress;
|
|
_startX = currentX;
|
|
_timer = 0f;
|
|
return stalled;
|
|
}
|
|
}
|
|
}
|