diff --git a/Assets/_Game/Scripts/Editor/Enemies/EnemyLocomotionEditor.cs b/Assets/_Game/Scripts/Editor/Enemies/EnemyLocomotionEditor.cs
index 09ec5f53..948fce8d 100644
--- a/Assets/_Game/Scripts/Editor/Enemies/EnemyLocomotionEditor.cs
+++ b/Assets/_Game/Scripts/Editor/Enemies/EnemyLocomotionEditor.cs
@@ -3,34 +3,24 @@ using UnityEditor;
using UnityEngine;
using BaseGames.AI;
using BaseGames.Enemies;
-using BaseGames.Enemies.Navigation;
namespace BaseGames.Editor
{
///
/// 自定义 Inspector。
/// PlayMode 下实时显示移动/巡逻状态,并对"原地不动"给出定位诊断:
- /// 模式、策略、当前路点与吸附目标、到达距离、是否在导航图上、目标是否可达。
+ /// 模式、策略、当前路点与目标、到达距离。
///
- /// 性能:刷新走 EditorApplication.update 定频(~5Hz),与游戏帧率解耦;昂贵查询
- /// (CanReach 会同步阻塞寻路、_maxSnapDistance 读取)限频 ~2Hz 并缓存——避免每帧
- /// 触发一次阻塞式寻路把帧数拖垮。
+ /// 性能:刷新走 EditorApplication.update 定频(~5Hz),与游戏帧率解耦。
///
[CustomEditor(typeof(EnemyLocomotion))]
public class EnemyLocomotionEditor : UnityEditor.Editor
{
private const double RepaintInterval = 0.2; // 面板刷新间隔(s),与游戏帧率解耦
- private const double HeavyInterval = 0.5; // 昂贵查询(CanReach 等)重算间隔(s)
private double _nextRepaintTime;
- private double _nextHeavyTime;
- // 昂贵查询的缓存(仅每 HeavyInterval 刷新一次)
- private bool _cachedCanReach;
- private bool _cachedCanReachValid;
- private float _cachedMaxSnap = -1f;
-
- // 退出 Play 期间:Application.isPlaying 仍为 true 但 PBWorld 已销毁,此时调 CanReach 会 NRE。
+ // 退出 Play 期间:Application.isPlaying 仍为 true 但场景已销毁,此时读取运行时状态可能 NRE。
// 收到 ExitingPlayMode 即停止一切运行时查询。
private bool _exitingPlay;
// 本帧是否绘制运行时区块——在 Layout 事件锁定、Repaint 复用,保证两趟控件数一致(否则 IMGUI 报错)。
@@ -123,20 +113,11 @@ namespace BaseGames.Editor
var nav = enemy != null ? enemy.Nav : null;
if (nav != null)
- {
- sb.AppendLine($"Nav 类型: {nav.GetType().Name} Nav.IsMoving: {nav.IsMoving} IsOnLink: {nav.IsOnLink} LinkType: {nav.CurrentLinkType}");
- if (nav is EnemyNavAgent ena && ena.RawNavAgent != null)
- {
- var raw = ena.RawNavAgent;
- sb.AppendLine($"在导航图上(HasValidPosition): {raw.HasValidPosition} IsFollowingAPath: {raw.IsFollowingAPath}");
- sb.AppendLine($"PB2d Agent Position: {raw.Position}");
- }
- }
+ sb.AppendLine($"Nav 类型: {nav.GetType().Name} IsMoving: {nav.IsMoving} HasArrived: {nav.HasArrived} IsBlocked: {nav.IsBlocked}");
else sb.AppendLine("Nav: null");
var mv = enemy != null ? enemy.Movement : null;
if (mv != null) sb.AppendLine($"EdgeSafeMargin(身体半宽+偏移): {mv.EdgeSafeMargin:F3}");
- sb.AppendLine($"_maxSnapDistance: {ReadMaxSnap(nav)}");
if (enemy != null) sb.AppendLine($"EnemyPos: {enemy.transform.position}");
// ── Waypoints ──
@@ -148,27 +129,9 @@ namespace BaseGames.Editor
int idx = loco.DebugWaypointIndex;
sb.AppendLine($"当前索引: {idx} / {(cnt > 0 ? cnt - 1 : 0)} ArriveRadius: {loco.DebugArriveRadius:F2}");
Vector2 goal = loco.DebugResolvedGoal;
- sb.AppendLine($"当前吸附目标(Resolved): {goal} ResolveOk: {loco.DebugResolveOk}");
+ sb.AppendLine($"当前目标点: {goal}");
if (enemy != null)
- sb.AppendLine($"到目标距离: {Vector2.Distance(enemy.transform.position, goal):F2}" +
- (nav != null ? $" CanReach: {nav.CanReach(goal)}" : ""));
-
- if (wps != null)
- {
- sb.AppendLine("路点逐个吸附检测(点击时实时计算):");
- for (int i = 0; i < wps.Length; i++)
- {
- if (wps[i] == null) { sb.AppendLine($" [{i}] "); continue; }
- Vector2 rawp = wps[i].position;
- string snapStr = "(需 Play 且有 Nav)";
- if (nav != null)
- {
- bool ok = nav.ResolveStandablePoint(rawp, out var snapped);
- snapStr = $"snap ok={ok} {snapped} |rawY-snapY|={Mathf.Abs(rawp.y - snapped.y):F2}";
- }
- sb.AppendLine($" [{i}] {wps[i].name} raw={rawp} -> {snapStr}");
- }
- }
+ sb.AppendLine($"到目标距离: {Vector2.Distance(enemy.transform.position, goal):F2}");
}
// ── 诊断 ──
@@ -178,30 +141,15 @@ namespace BaseGames.Editor
return sb.ToString();
}
- private static string ReadMaxSnap(IPathAgent nav)
- {
- if (nav is EnemyNavAgent ena)
- {
- using var so = new SerializedObject(ena);
- var msd = so.FindProperty("_maxSnapDistance");
- if (msd != null) return msd.floatValue.ToString("F1");
- }
- return "(n/a)";
- }
-
// 纯文本诊断(与面板 HelpBox 同一判定逻辑,供报告文末结论)
- private static string Diagnose(EnemyLocomotion loco, EnemyBase enemy, IPathAgent nav)
+ private static string Diagnose(EnemyLocomotion loco, EnemyBase enemy, IEnemyNavigator nav)
{
if (!Application.isPlaying) return "编辑期:仅静态配置,进入 Play 后可判定运行时问题。";
if (loco.CurrentMode != LocomotionMode.Patrol)
return $"→ 不动主因:LocomotionMode={loco.CurrentMode}(非 Patrol)。AI 尚未进入巡逻态,TickPatrol 不执行。" +
(enemy?.Brain != null ? $" 当前 Brain 状态='{enemy.Brain.CurrentStateName}'——检查该状态是否/何时切到巡逻。" : "");
- bool mapped = !(nav is EnemyNavAgent e && e.RawNavAgent != null) || ((EnemyNavAgent)nav).RawNavAgent.HasValidPosition;
- if (!mapped) return "→ 敌人不在 NavGraph 上(HasValidPosition=false):RequestMoveTo 被忽略。检查贴地/是否在已 bake 的 NavSurface。";
- if (loco.DebugStrategy == PatrolStrategy.Waypoints && !loco.DebugResolveOk)
- return "→ 当前路点吸附失败:超出 _maxSnapDistance。调大或把路点摆近平台。";
- if (nav != null && !nav.CanReach(loco.DebugResolvedGoal))
- return "→ 目标不可达:与吸附目标不连通,或隔着不可穿越 NavLink。";
+ if (nav != null && !nav.IsMoving && !nav.HasArrived && !nav.IsBlocked)
+ return "→ 已请求移动但没有推进 —— 检查 EnemyMovement 速度/受阻/刚体约束、是否被其他状态覆盖输入。";
return "→ 巡逻链路各项正常(若仍不动,检查 EnemyMovement 速度/受阻/刚体约束)。";
}
@@ -210,11 +158,6 @@ namespace BaseGames.Editor
var loco = (EnemyLocomotion)target;
var enemy = loco.DebugEnemy;
- // 是否到了重算昂贵查询的时刻(限频)
- double now = EditorApplication.timeSinceStartup;
- bool doHeavy = now >= _nextHeavyTime;
- if (doHeavy) _nextHeavyTime = now + HeavyInterval;
-
EditorGUILayout.LabelField("运行时调试", EditorStyles.boldLabel);
// ── 模式 / 策略 ─────────────────────────────────────────────
@@ -233,25 +176,13 @@ namespace BaseGames.Editor
// ── 导航代理状态 ────────────────────────────────────────────
var nav = enemy.Nav;
- bool agentMapped = true; // 非 PB2d 代理默认视为有效
- bool navMoving = nav != null && nav.IsMoving;
- if (nav is EnemyNavAgent ena && ena.RawNavAgent != null)
- agentMapped = ena.RawNavAgent.HasValidPosition;
+ bool navMoving = nav != null && nav.IsMoving;
- Row("在导航图上 (Mapped)", agentMapped ? "是" : "否 —— 敌人不在 NavGraph 上",
- agentMapped ? Green : Red);
+ Row("Nav 类型", nav != null ? nav.GetType().Name : "null", White);
Row("Nav 正在寻路/移动", navMoving ? "是" : "否", navMoving ? Green : Gray);
- // 身体宽度 / 吸附距离(_maxSnapDistance 运行期不变 → 只读一次缓存)
var mv = enemy.Movement;
if (mv != null) Row("EdgeSafeMargin(身体半宽+偏移)", mv.EdgeSafeMargin.ToString("F2"), White);
- if (_cachedMaxSnap < 0f && nav is EnemyNavAgent ena2)
- {
- using var so = new SerializedObject(ena2);
- var msd = so.FindProperty("_maxSnapDistance");
- _cachedMaxSnap = msd != null ? msd.floatValue : 0f;
- }
- if (_cachedMaxSnap >= 0f) Row("_maxSnapDistance", _cachedMaxSnap.ToString("F1"), White);
// ── 路点巡逻细节 ────────────────────────────────────────────
if (loco.DebugStrategy == PatrolStrategy.Waypoints)
@@ -266,32 +197,15 @@ namespace BaseGames.Editor
if (wps != null && idx >= 0 && idx < cnt && wps[idx] != null)
{
- Vector2 raw = wps[idx].position;
Vector2 goal = loco.DebugResolvedGoal;
- Row("原始路点", $"{wps[idx].name} {raw}", White);
- Row("吸附目标 (Resolved)", loco.DebugResolveOk ? goal.ToString() : $"{goal} (吸附失败,回落原始点)",
- loco.DebugResolveOk ? Green : Red);
+ Row("当前目标点", goal.ToString(), White);
float dist = Vector2.Distance(enemy.transform.position, goal);
bool arrived = dist <= loco.DebugArriveRadius;
Row("到目标距离 / 到达半径", $"{dist:F2} / {loco.DebugArriveRadius:F2}{(arrived ? " (已到达)" : "")}",
arrived ? Green : White);
- // CanReach 会同步阻塞寻路 → 仅限频重算并缓存。
- // 额外守卫 !_exitingPlay && isPlaying:退出 Play 那一刻 PBWorld 已销毁,此时调会 NRE。
- if (doHeavy && nav != null && !_exitingPlay && Application.isPlaying)
- {
- _cachedCanReach = nav.CanReach(goal);
- _cachedCanReachValid = true;
- }
- if (_cachedCanReachValid)
- Row("目标可达 (CanReach)", _cachedCanReach ? "是" : "否 —— 起点/终点不连通",
- _cachedCanReach ? Green : Red);
- else
- Row("目标可达 (CanReach)", "计算中…", Gray);
-
- DrawDiagnosis(patrolActive, agentMapped, loco.DebugResolveOk,
- _cachedCanReachValid && _cachedCanReach, navMoving, arrived);
+ DrawDiagnosis(patrolActive, navMoving, arrived);
}
}
@@ -300,8 +214,7 @@ namespace BaseGames.Editor
}
// ── "原地不动" 定位诊断 ─────────────────────────────────────────
- private static void DrawDiagnosis(bool patrolActive, bool mapped,
- bool resolveOk, bool canReach, bool navMoving, bool arrived)
+ private static void DrawDiagnosis(bool patrolActive, bool navMoving, bool arrived)
{
EditorGUILayout.Space(4f);
string msg; MessageType type;
@@ -312,25 +225,9 @@ namespace BaseGames.Editor
"需触发 AI 切到巡逻状态。";
type = MessageType.Warning;
}
- else if (!mapped)
- {
- msg = "敌人不在导航图上(HasValidPosition=false)—— RequestMoveTo/UpdatePath 被直接忽略。" +
- "检查:碰撞体底部是否贴地(原点=脚底)、是否站在已 bake 的 NavSurface 上、PointMappingDistance(默认0.2m)。";
- type = MessageType.Error;
- }
- else if (!resolveOk)
- {
- msg = "路点吸附失败 —— 目标离所有烘焙段都超过 _maxSnapDistance。调大 _maxSnapDistance 或把路点摆近平台。";
- type = MessageType.Error;
- }
- else if (!canReach)
- {
- msg = "目标不可达 —— 起点与吸附目标不在同一连通区,或中间隔着不可穿越的 NavLink(跳/落/爬)。";
- type = MessageType.Error;
- }
else if (!navMoving && !arrived)
{
- msg = "已寻路成功但没有移动 —— 检查 EnemyMovement 速度/受阻(WouldBlockAhead 夹停)、刚体约束、是否被其他状态覆盖输入。";
+ msg = "已请求移动但没有推进 —— 检查 EnemyMovement 速度/受阻(WouldBlockAhead 夹停)、刚体约束、是否被其他状态覆盖输入。";
type = MessageType.Warning;
}
else
diff --git a/Assets/_Game/Scripts/Enemies/EnemyBase.cs b/Assets/_Game/Scripts/Enemies/EnemyBase.cs
index 0e5cc359..6ed64367 100644
--- a/Assets/_Game/Scripts/Enemies/EnemyBase.cs
+++ b/Assets/_Game/Scripts/Enemies/EnemyBase.cs
@@ -13,7 +13,7 @@ namespace BaseGames.Enemies
/// 敌人基类(架构 07_EnemyModule §1)。
/// 实现 IDamageable,为 Behavior Designer 任务提供统一虚方法接口。
/// 包含:BD 接口、受击、死亡流程。
- /// ⚠️ _nav 字段类型为 IPathAgent(在 BaseGames.Enemies.Navigation 中实现具体类)。
+ /// ⚠️ _nav 字段类型为 IEnemyNavigator(在 BaseGames.Enemies.Navigation 中实现具体类)。
/// 实现 IPoolable:配合 PooledObject 支持对象池复用,避免频繁 Destroy/Instantiate。
///
public class EnemyBase : MonoBehaviour, IDamageable, IPoolable
@@ -60,10 +60,10 @@ namespace BaseGames.Enemies
///
[SerializeField] private BaseGames.Core.Events.TransformEventChannelSO _onPlayerSpawned;
- // ── 导航代理(IPathAgent;由 EnemyNavAgent 实现)───────────────────
+ // ── 导航代理(IEnemyNavigator;由 GroundNavigator/FlyingNavigator 实现)─────
// 通过接口引用,避免对 Navigation 程序集的直接依赖。
- // 由子类 / Inspector 注入,或者运行时 GetComponent() 获取。
- protected IPathAgent _nav;
+ // 由子类 / Inspector 注入,或者运行时 GetComponent() 获取。
+ protected IEnemyNavigator _nav;
// 移动执行器(IEnemyLocomotion;由 EnemyLocomotion 在 Navigation 程序集实现,运行时发现)
protected IEnemyLocomotion _locomotion;
@@ -216,7 +216,7 @@ namespace BaseGames.Enemies
}
// BD 任务访问接口(公共只读属性)────────────────────────────────
- public IPathAgent Nav => _nav;
+ public IEnemyNavigator Nav => _nav;
// 惰性发现兜底:关域重载后 Awake 设的实例字段可能残留为 null(编辑器快速迭代),
// 首次访问时按需补发现,保证编辑器与构建下都不为空。
public IEnemyLocomotion Locomotion => _locomotion ?? (_locomotion = GetComponentInChildren(true));
@@ -256,7 +256,7 @@ namespace BaseGames.Enemies
// ── BD 行为树接口(虚方法)────────────────────────────────────────
public virtual void MoveTo(Vector2 target)
- => _nav?.RequestMoveTo(target);
+ => _nav?.MoveTowards(target);
public virtual void MoveInDirection(float dir)
{
@@ -284,7 +284,7 @@ namespace BaseGames.Enemies
public virtual void StopMovement()
{
- _nav?.StopNavigation();
+ _nav?.Stop();
if (_movement != null) _movement.PendingInput.WantStop = true;
}
@@ -547,7 +547,7 @@ namespace BaseGames.Enemies
_stateObjs[EnemyStateType.KnockUp] = new EnemyKnockUpState();
_stateObjs[EnemyStateType.Dead] = new EnemyDeadState();
- _nav = GetComponent() ?? new NullPathAgent();
+ _nav = GetComponent() ?? new NullEnemyNavigator();
_locomotion = GetComponentInChildren(true);
if (_locomotion == null)
Debug.LogError($"EnemyBase 未找到 EnemyLocomotion 组件:{name}", this);
@@ -771,7 +771,7 @@ namespace BaseGames.Enemies
public virtual void OnDespawn()
{
_abilities.InterruptAll(InterruptReason.Dead);
- _nav?.StopNavigation();
+ _nav?.Stop();
// GO 停用时 EnemyAiBrain.Update 自然停止,无需显式处理。
}
diff --git a/Assets/_Game/Scripts/Enemies/FlyingEnemy.cs b/Assets/_Game/Scripts/Enemies/FlyingEnemy.cs
index 68a7e013..e5f5c34e 100644
--- a/Assets/_Game/Scripts/Enemies/FlyingEnemy.cs
+++ b/Assets/_Game/Scripts/Enemies/FlyingEnemy.cs
@@ -7,7 +7,7 @@ namespace BaseGames.Enemies
///
/// 飞行敌人基类。
///
- /// 导航由 实现(IPathAgent),
+ /// 导航由 实现(IEnemyNavigator),
/// AI 行为逻辑由挂载的 Behavior Designer 树驱动。
/// 本类仅负责:
///
diff --git a/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs b/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs
index f40c49a9..3bc6e3c9 100644
--- a/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs
+++ b/Assets/_Game/Scripts/Enemies/Navigation/EnemyLocomotion.cs
@@ -5,7 +5,7 @@ namespace BaseGames.Enemies
{
///
/// 敌人移动执行器:唯一的移动/朝向入口。AI 状态与能力经 IEnemyLocomotion
- /// 声明意图,本组件每帧把当前模式翻译为对 EnemyBase/IPathAgent 的调用。
+ /// 声明意图,本组件每帧把当前模式翻译为对 EnemyBase/IEnemyNavigator 的调用。
/// 取代散落的 MoveTo/StopMovement/FacePlayer/FaceTarget 直调与三个协程能力。
///
[DisallowMultipleComponent]
@@ -38,9 +38,8 @@ namespace BaseGames.Enemies
private int _wpIndex = -1;
private int _wpDir = 1;
private bool _warnedNoWaypoints;
- // 当前路点吸附后的"站得住"目标(宽度由 Nav 层解析,本层不感知身体尺寸)
+ // 当前路点坐标(导航图已移除,直接用原始坐标;走不到会被夹停)
private Vector2 _wpResolvedGoal;
- private bool _wpResolveOk; // 上次路点是否成功吸附到导航段(调试用)
// Wander 到点停顿状态
private bool _wanderPausing;
private float _wanderPauseTimer;
@@ -141,17 +140,19 @@ namespace BaseGames.Enemies
}
///
- /// 段内随机游走:随机点限制在当前所站的导航段上(不跨 NavLink,避免崖边夹停/卡 link),
- /// 到达一个点后原地停顿 [_wanderPauseMin, _wanderPauseMax] 秒(期间播 Idle),再挑下一个点。
+ /// 就近随机游走:朝随机取的目标点走,**到达或被地形夹停**即视为本次游走结束,
+ /// 停顿 [_wanderPauseMin, _wanderPauseMax] 秒(期间播 Idle)后再挑下一个点。
+ /// 走到平台边缘停下转身是预期表现——可达性由移动层夹紧决定,不做地形扫描。
///
private void TickWander()
{
- if (_enemy.Nav == null) return;
+ var nav = _enemy.Nav;
+ if (nav == null) return;
- // 移动中:清停顿态,等到达
- if (_enemy.Nav.IsMoving) { _wanderPausing = false; return; }
+ // 仍在推进:清停顿态,等到达/受阻
+ if (nav.IsMoving) { _wanderPausing = false; return; }
- // 已到达(或尚未出发):先停顿计时,再挑下一个点
+ // 到达、受阻或尚未出发:先停顿计时,再挑下一个点
if (!_wanderPausing)
{
_wanderPausing = true;
@@ -162,7 +163,7 @@ namespace BaseGames.Enemies
if (_wanderPauseTimer <= 0f)
{
_wanderPausing = false;
- _enemy.Nav.WalkToRandomOnSegment();
+ if (nav.TryPickWanderPoint(out var point)) nav.MoveTowards(point);
}
}
@@ -213,7 +214,7 @@ namespace BaseGames.Enemies
Vector2.Distance(_enemy.transform.position, _wpResolvedGoal) <= _waypointArriveRadius;
// 受阻结算:执行层已把敌人带到最近可达点并停下(或原地停) → 视为本路点完成。
- bool obstructedSettled = nav != null && nav.LastMoveObstructed && !nav.IsMoving;
+ bool obstructedSettled = nav != null && nav.IsBlocked;
if (_wpIndex < 0 || wpArrived || obstructedSettled)
{
@@ -232,31 +233,21 @@ namespace BaseGames.Enemies
AdvanceWaypoint();
SetWaypointGoal();
}
- else if (nav != null && !nav.IsMoving && !nav.LastMoveObstructed)
+ else if (nav != null && !nav.IsMoving && !nav.IsBlocked && !nav.HasArrived)
{
- // 瞬态:刚出生尚未映射那一帧的 MoveTo 失败 → 重发(RequestMoveTo 自带 0.25s 防抖)。
+ // 瞬态:刚出生尚未映射那一帧的 MoveTo 失败 → 重发(MoveTowards 自带防抖)。
// 仅"未受阻"时重发;受阻由上面 obstructedSettled 分支结算,不再无限重发不可达点。
- _enemy.MoveTo(_wpResolvedGoal);
+ nav.MoveTowards(_wpResolvedGoal);
}
break;
}
}
- ///
- /// 解析当前路点为"身体站得住的可达点"并出发。宽度处理下沉给 Nav 层(),
- /// 本层只递原始路点坐标、不感知身体尺寸。吸附失败=路点摆得离导航面太远,显式报错暴露根因,不静默兜底。
- ///
+ /// 取当前路点坐标并出发。路点若摆在崖外/墙后,敌人会走到边缘被夹停 → IsBlocked → 结算推进下一个。
private void SetWaypointGoal()
{
- Vector2 raw = _waypoints[_wpIndex].position;
- _wpResolveOk = _enemy.Nav != null && _enemy.Nav.ResolveStandablePoint(raw, out _wpResolvedGoal);
- if (!_wpResolveOk)
- {
- _wpResolvedGoal = raw;
- Debug.LogWarning($"[EnemyLocomotion] 路点 '{_waypoints[_wpIndex].name}'(index {_wpIndex}) 无法吸附到任何可行走导航段" +
- "(超出搜索半径)。请检查该路点是否摆放在贴近地面/平台的可行走处。", this);
- }
- _enemy.MoveTo(_wpResolvedGoal);
+ _wpResolvedGoal = _waypoints[_wpIndex].position;
+ _enemy.Nav?.MoveTowards(_wpResolvedGoal);
}
private void AdvanceWaypoint()
@@ -280,7 +271,6 @@ namespace BaseGames.Enemies
public Transform[] DebugWaypoints => _waypoints;
public int DebugWaypointIndex => _wpIndex;
public Vector2 DebugResolvedGoal => _wpResolvedGoal;
- public bool DebugResolveOk => _wpResolveOk;
public float DebugArriveRadius => _waypointArriveRadius;
public bool DebugWanderPausing => _wanderPausing;
@@ -298,11 +288,11 @@ namespace BaseGames.Enemies
if (next != null) Gizmos.DrawLine(_waypoints[i].position, next.position);
}
- // 运行期:当前吸附目标 + 到达半径 + 连线(绿=吸附成功 红=失败回落原始点)
+ // 运行期:当前目标点 + 到达半径 + 连线
if (Application.isPlaying && _wpIndex >= 0)
{
Vector3 from = _enemy != null ? _enemy.transform.position : transform.position;
- Gizmos.color = _wpResolveOk ? Color.green : Color.red;
+ Gizmos.color = Color.green;
Gizmos.DrawWireSphere(_wpResolvedGoal, 0.22f);
Gizmos.DrawLine(from, _wpResolvedGoal);
Gizmos.color = new Color(1f, 0.9f, 0.2f, 0.7f);