Godot Navigation2D.GetSimplePath()返回异常路径问题求助
问题现象
使用Godot引擎进行C#游戏开发时,调用Navigation2D.GetSimplePath方法实现敌人发现玩家后的自动追击寻路逻辑。按照预期,传入起止坐标后该方法应返回存储敌人位置到玩家位置导航路径的Vector2数组,但实际运行时敌人移动方向与预期完全偏离。
已尝试的排查方案
- 最初直接传入敌人与玩家的Position坐标作为寻路起止点,代码如下:
var from = Enemy.Position; var to = PlayerRef.Position; // Nav为场景中挂载的Navigation2D节点 var paths = Nav.GetSimplePath(from, to); Enemy.Status.NavPath = new Stack<Vector2>(paths);
运行后得到错误寻路结果,猜测是坐标空间不匹配,尝试将起止点转换为Navigation2D节点下的本地坐标:
// Nav为场景中挂载的Navigation2D节点 var from = Nav.ToLocal(Enemy.GlobalPosition); var to = Nav.ToLocal(PlayerRef.GlobalPosition);
后续多次测试不同节点间全局坐标与本地坐标的转换组合,均返回错误寻路结果,多日排查未定位到明显疏漏。
补充说明:该问题仅在代码重构后出现,重构前所有寻路逻辑耦合在单个敌人类中时可正常运行。
当前追击逻辑完整代码
using Godot; using ThemedHorrorJam5.Scripts.Enum; using ThemedHorrorJam5.Scripts.Patterns.StateMachine; using ThemedHorrorJam5.Scripts.GDUtils; using System.Collections.Generic; using System.Linq; namespace ThemedHorrorJam5.Entities { public class ChaseEnemyState : State { private Navigation2D? GetLevelNavigation() { var nodeTuples = Enemy.GetTree().GetNavigation2dNodes(); if (nodeTuples.Item1) return nodeTuples.Item2[0]; return null; } private Navigation2D Nav { get; set; } private EnemyV4 Enemy { get; set; } private PlayerV2 PlayerRef { get; set; } public ChaseEnemyState(EnemyV4 enemy) { this.Name = EnemyBehaviorStates.ChasePlayer.GetDescription(); Enemy = enemy; (var hasPlayer, PlayerRef) = Enemy.GetTree().GetPlayerNode(); if (!hasPlayer) { Logger.Error("Player ref not found on scene tree"); } (var hasNav, var navNodes) = Enemy.GetTree().GetNavigation2dNodes(); if (hasNav && navNodes != null) { Nav = navNodes[0]; } this.OnEnter += () => this.Logger.Debug("ChaseEnemyState OnEnter called"); this.OnExit += () => this.Logger.Debug("ChaseEnemyState Exit called"); this.OnFrame += ChasePlayer; } private void ChasePlayer(float delta) { if (Enemy.IsDebugging && Enemy.HasNode("Line2D")) { Enemy.Status.Line = (Line2D)Enemy.GetNode("Line2D"); } if (Nav!=null) { var from = Nav.ToLocal(Enemy.GlobalPosition); var to = Nav.ToLocal(PlayerRef.GlobalPosition); var paths = Nav.GetSimplePath(from, to); Enemy.Status.NavPath = new Stack<Vector2>(paths); if (Enemy.Status.Line != null) { Enemy.Status.Line.Points = Enemy.Status.NavPath.ToArray(); } var distance_to_walk = Enemy.MoveSpeed * delta; while (distance_to_walk > 0f && Enemy.Status.NavPath.Count > 0f) { var distance_to_next_point = Enemy.Position.DistanceTo(Enemy.Status.NavPath.Peek()); if (distance_to_walk <= distance_to_next_point) { var newPosition = Enemy.Position.DirectionTo(Enemy.Status.NavPath.Peek()) * distance_to_walk; Enemy.Status.VisionManager.UpdateFacingDirection(newPosition.Normalized()); Enemy.Position += newPosition; } else { var newPosition = Enemy.Status.NavPath.Pop(); Enemy.Status.VisionManager.UpdateFacingDirection(newPosition.Normalized()); if (Enemy.GetSlideCount() > 0) { Enemy.HandleMovableObstacleCollision(newPosition); } Enemy.Position = newPosition; } distance_to_walk -= distance_to_next_point; } } else { Logger.Error("Navigation2D not found"); } if (Enemy.Status.CurrentCoolDownCounter > 0) { Enemy.Status.CurrentCoolDownCounter -= delta; } } } }
附加排查材料
已提供运行效果截图辅助说明问题:图中绿色标识为玩家,蓝色标识为敌人,调试变量from、to为寻路传入的起止坐标,黄色区域为敌人视野锥,指向敌人当前移动方向,Target为玩家节点别名,红色线条为通过Line2D绘制的敌人寻路路径,同时提供了测试关卡、敌人场景的结构截图,寻求问题排查指引。
内容的提问来源于stack exchange,提问作者Terrance
相关产品推荐
相关产品推荐

