fix(nav): 修复 nav 寻路核心用法——重寻路防抖 + allowCloseEnoughPath
根因1: PathBerserker2d NavAgent.UpdatePath 明确禁止每帧调用(路径计算跨帧,每帧重启则永不完成、 agent永不移动),而追击每帧 MoveTo→RequestMoveTo→UpdatePath。修: EnemyNavAgent.RequestMoveTo 加防抖(目标位移阈值0.5m + 最小间隔0.25s),让路径算完并跟随;StopNavigation 复位。 根因2: NavAgent.allowCloseEnoughPath 默认false→追击玩家(常不在导航段上)寻路直接失败。 修: 脚手架(4个PlaceExxx)+E001 prefab 设为 true(寻路到最近可达点)。 验证: 敌人 nav 巡逻/追击已能真正跟随路径移动(following=True)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -384,7 +384,7 @@ MonoBehaviour:
|
|||||||
- 1
|
- 1
|
||||||
- 1
|
- 1
|
||||||
- 1
|
- 1
|
||||||
allowCloseEnoughPath: 0
|
allowCloseEnoughPath: 1
|
||||||
movementSpeed: 5
|
movementSpeed: 5
|
||||||
cornerSpeed: 100
|
cornerSpeed: 100
|
||||||
jumpSpeed: 5
|
jumpSpeed: 5
|
||||||
@@ -436,6 +436,8 @@ MonoBehaviour:
|
|||||||
_groundMask:
|
_groundMask:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_Bits: 4294967295
|
m_Bits: 4294967295
|
||||||
|
_repathTargetThreshold: 0.5
|
||||||
|
_repathMinInterval: 0.25
|
||||||
--- !u!114 &3225188436228842581
|
--- !u!114 &3225188436228842581
|
||||||
MonoBehaviour:
|
MonoBehaviour:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
|||||||
@@ -302,7 +302,8 @@ namespace BaseGames.Editor
|
|||||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||||
GetOrAddComponent<EnemyNavAgent>(go);
|
GetOrAddComponent<EnemyNavAgent>(go);
|
||||||
GetOrAddComponent<NavAgent>(go);
|
NavAgent navAgent = GetOrAddComponent<NavAgent>(go);
|
||||||
|
AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点
|
||||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||||
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
||||||
|
|
||||||
@@ -464,7 +465,8 @@ namespace BaseGames.Editor
|
|||||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||||
GetOrAddComponent<EnemyNavAgent>(go);
|
GetOrAddComponent<EnemyNavAgent>(go);
|
||||||
GetOrAddComponent<NavAgent>(go);
|
NavAgent navAgent = GetOrAddComponent<NavAgent>(go);
|
||||||
|
AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点
|
||||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||||
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
||||||
|
|
||||||
@@ -665,7 +667,8 @@ namespace BaseGames.Editor
|
|||||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||||
GetOrAddComponent<EnemyNavAgent>(go);
|
GetOrAddComponent<EnemyNavAgent>(go);
|
||||||
GetOrAddComponent<NavAgent>(go);
|
NavAgent navAgent = GetOrAddComponent<NavAgent>(go);
|
||||||
|
AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点
|
||||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||||
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
||||||
|
|
||||||
@@ -1000,7 +1003,8 @@ namespace BaseGames.Editor
|
|||||||
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
EnemyStats enemyStats = GetOrAddComponent<EnemyStats>(go);
|
||||||
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
EnemyMovement movement = GetOrAddComponent<EnemyMovement>(go);
|
||||||
GetOrAddComponent<EnemyNavAgent>(go);
|
GetOrAddComponent<EnemyNavAgent>(go);
|
||||||
GetOrAddComponent<NavAgent>(go);
|
NavAgent navAgent = GetOrAddComponent<NavAgent>(go);
|
||||||
|
AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点
|
||||||
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
GetOrAddComponent<TransformBasedMovement>(go); // required by EnemyNavAgent [RequireComponent]
|
||||||
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
PhysicsPerceptionSystem sensorHub = GetOrAddComponent<PhysicsPerceptionSystem>(go);
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ namespace BaseGames.Enemies.Navigation
|
|||||||
[Tooltip("边缘检测 LayerMask(留空 = 所有层)")]
|
[Tooltip("边缘检测 LayerMask(留空 = 所有层)")]
|
||||||
[SerializeField] private LayerMask _groundMask = ~0;
|
[SerializeField] private LayerMask _groundMask = ~0;
|
||||||
|
|
||||||
|
[Header("重寻路防抖(PathBerserker2d 不可每帧 UpdatePath,否则路径永远算不完)")]
|
||||||
|
[Tooltip("目标位移阈值(m):目标移动超过此值才重算路径")]
|
||||||
|
[SerializeField] private float _repathTargetThreshold = 0.5f;
|
||||||
|
[Tooltip("两次重算最小间隔(s):留出跨帧路径计算完成的时间")]
|
||||||
|
[SerializeField] private float _repathMinInterval = 0.25f;
|
||||||
|
|
||||||
|
// 重寻路防抖状态
|
||||||
|
private Vector2 _lastPathGoal;
|
||||||
|
private bool _hasPathGoal;
|
||||||
|
private float _lastPathTime;
|
||||||
|
|
||||||
// ── IPathAgent 公开状态 ────────────────────────────────────────
|
// ── IPathAgent 公开状态 ────────────────────────────────────────
|
||||||
public bool IsMoving => _navAgent != null && _navAgent.IsFollowingAPath;
|
public bool IsMoving => _navAgent != null && _navAgent.IsFollowingAPath;
|
||||||
public bool IsOnLink => _navAgent != null && _navAgent.IsOnLink;
|
public bool IsOnLink => _navAgent != null && _navAgent.IsOnLink;
|
||||||
@@ -120,12 +131,27 @@ namespace BaseGames.Enemies.Navigation
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ── IPathAgent ─────────────────────────────────────────────────
|
// ── IPathAgent ─────────────────────────────────────────────────
|
||||||
public void RequestMoveTo(Vector2 target) => _navAgent?.UpdatePath(target);
|
public void RequestMoveTo(Vector2 target)
|
||||||
|
{
|
||||||
|
if (_navAgent == null) return;
|
||||||
|
// PathBerserker2d 明确警告不可每帧 UpdatePath(路径计算跨帧,每帧重启则永不完成、agent 永不移动)。
|
||||||
|
// 防抖:目标未明显移动 且 距上次重算不足间隔 → 跳过,让当前路径算完并跟随。
|
||||||
|
if (_hasPathGoal
|
||||||
|
&& Vector2.Distance(target, _lastPathGoal) < _repathTargetThreshold
|
||||||
|
&& Time.time - _lastPathTime < _repathMinInterval)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_lastPathGoal = target;
|
||||||
|
_hasPathGoal = true;
|
||||||
|
_lastPathTime = Time.time;
|
||||||
|
_navAgent.UpdatePath(target);
|
||||||
|
}
|
||||||
|
|
||||||
public void StopNavigation()
|
public void StopNavigation()
|
||||||
{
|
{
|
||||||
_activeHandler?.AbortLinkTraversal();
|
_activeHandler?.AbortLinkTraversal();
|
||||||
_activeHandler = null;
|
_activeHandler = null;
|
||||||
|
_hasPathGoal = false; // 复位防抖,下次请求立即重新寻路
|
||||||
_navAgent?.Stop();
|
_navAgent?.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user