From 643f63c7374605121ce6752a5c651667047f74d8 Mon Sep 17 00:00:00 2001 From: Joywayer Date: Thu, 9 Jul 2026 16:43:52 +0800 Subject: [PATCH] =?UTF-8?q?fix(nav):=20=E4=BF=AE=E5=A4=8D=20nav=20?= =?UTF-8?q?=E5=AF=BB=E8=B7=AF=E6=A0=B8=E5=BF=83=E7=94=A8=E6=B3=95=E2=80=94?= =?UTF-8?q?=E2=80=94=E9=87=8D=E5=AF=BB=E8=B7=AF=E9=98=B2=E6=8A=96=20+=20al?= =?UTF-8?q?lowCloseEnoughPath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因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) --- .../Prefabs/Enemies/E001/ENM_CaoZhi.prefab | 4 ++- .../Editor/Scene/SceneObjectPlacerTool.cs | 12 +++++--- .../Enemies/Navigation/EnemyNavAgent.cs | 28 ++++++++++++++++++- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/Assets/_Game/Prefabs/Enemies/E001/ENM_CaoZhi.prefab b/Assets/_Game/Prefabs/Enemies/E001/ENM_CaoZhi.prefab index 8233fc18..b173d598 100644 --- a/Assets/_Game/Prefabs/Enemies/E001/ENM_CaoZhi.prefab +++ b/Assets/_Game/Prefabs/Enemies/E001/ENM_CaoZhi.prefab @@ -384,7 +384,7 @@ MonoBehaviour: - 1 - 1 - 1 - allowCloseEnoughPath: 0 + allowCloseEnoughPath: 1 movementSpeed: 5 cornerSpeed: 100 jumpSpeed: 5 @@ -436,6 +436,8 @@ MonoBehaviour: _groundMask: serializedVersion: 2 m_Bits: 4294967295 + _repathTargetThreshold: 0.5 + _repathMinInterval: 0.25 --- !u!114 &3225188436228842581 MonoBehaviour: m_ObjectHideFlags: 0 diff --git a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs index 378ab828..71f7dd34 100644 --- a/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs +++ b/Assets/_Game/Scripts/Editor/Scene/SceneObjectPlacerTool.cs @@ -302,7 +302,8 @@ namespace BaseGames.Editor EnemyStats enemyStats = GetOrAddComponent(go); EnemyMovement movement = GetOrAddComponent(go); GetOrAddComponent(go); - GetOrAddComponent(go); + NavAgent navAgent = GetOrAddComponent(go); + AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点 GetOrAddComponent(go); // required by EnemyNavAgent [RequireComponent] PhysicsPerceptionSystem sensorHub = GetOrAddComponent(go); @@ -464,7 +465,8 @@ namespace BaseGames.Editor EnemyStats enemyStats = GetOrAddComponent(go); EnemyMovement movement = GetOrAddComponent(go); GetOrAddComponent(go); - GetOrAddComponent(go); + NavAgent navAgent = GetOrAddComponent(go); + AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点 GetOrAddComponent(go); // required by EnemyNavAgent [RequireComponent] PhysicsPerceptionSystem sensorHub = GetOrAddComponent(go); @@ -665,7 +667,8 @@ namespace BaseGames.Editor EnemyStats enemyStats = GetOrAddComponent(go); EnemyMovement movement = GetOrAddComponent(go); GetOrAddComponent(go); - GetOrAddComponent(go); + NavAgent navAgent = GetOrAddComponent(go); + AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点 GetOrAddComponent(go); // required by EnemyNavAgent [RequireComponent] PhysicsPerceptionSystem sensorHub = GetOrAddComponent(go); @@ -1000,7 +1003,8 @@ namespace BaseGames.Editor EnemyStats enemyStats = GetOrAddComponent(go); EnemyMovement movement = GetOrAddComponent(go); GetOrAddComponent(go); - GetOrAddComponent(go); + NavAgent navAgent = GetOrAddComponent(go); + AssignBool(navAgent, "allowCloseEnoughPath", true); // 追击近似目标(玩家常不在导航段上)寻路到最近可达点 GetOrAddComponent(go); // required by EnemyNavAgent [RequireComponent] PhysicsPerceptionSystem sensorHub = GetOrAddComponent(go); diff --git a/Assets/_Game/Scripts/Enemies/Navigation/EnemyNavAgent.cs b/Assets/_Game/Scripts/Enemies/Navigation/EnemyNavAgent.cs index 82650a07..e4a5c232 100644 --- a/Assets/_Game/Scripts/Enemies/Navigation/EnemyNavAgent.cs +++ b/Assets/_Game/Scripts/Enemies/Navigation/EnemyNavAgent.cs @@ -29,6 +29,17 @@ namespace BaseGames.Enemies.Navigation [Tooltip("边缘检测 LayerMask(留空 = 所有层)")] [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 公开状态 ──────────────────────────────────────── public bool IsMoving => _navAgent != null && _navAgent.IsFollowingAPath; public bool IsOnLink => _navAgent != null && _navAgent.IsOnLink; @@ -120,12 +131,27 @@ namespace BaseGames.Enemies.Navigation } // ── 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() { _activeHandler?.AbortLinkTraversal(); _activeHandler = null; + _hasPathGoal = false; // 复位防抖,下次请求立即重新寻路 _navAgent?.Stop(); }