Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/unity3d/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实现中的特定A*寻路问题_C#_Unity3d_Path Finding_A Star - Fatal编程技术网

C# 实现中的特定A*寻路问题

C# 实现中的特定A*寻路问题,c#,unity3d,path-finding,a-star,C#,Unity3d,Path Finding,A Star,我的A*实现有一些问题。它偶尔会决定在我的网格上做一些奇怪的事情,比如忽略移动成本,在高成本区域移动,或者在回到正轨之前走错方向 我正式花了太多的时间在这上面,然后我想承认,所以我想找一双新鲜的眼睛 private List<Vector2> PathFromTo(Vector2 startID, Vector2 targetID){ List<Vector2> path = new List<Vector2> (); List<Node

我的A*实现有一些问题。它偶尔会决定在我的网格上做一些奇怪的事情,比如忽略移动成本,在高成本区域移动,或者在回到正轨之前走错方向

我正式花了太多的时间在这上面,然后我想承认,所以我想找一双新鲜的眼睛

private List<Vector2> PathFromTo(Vector2 startID, Vector2 targetID){
    List<Vector2> path = new List<Vector2> ();
    List<Node> closedList = new List<Node> ();
    List<Node> openList = new List<Node> ();
    Node startNode = nodeList.Find (tgt => tgt.nodeID == new Vector2 (startID.x, startID.y));
    if (startNode == null)
        return path;
    Node targetNode = nodeList.Find (tgt => tgt.nodeID == new Vector2 (targetID.x, targetID.y));
    if (targetNode == null)
        return path;

    openList.Add (startNode);

    while (openList.Count > 0) {
        Node current = openList [0];
        for (int i = 1; i < openList.Count; i++) 
            if (openList [i].GetFCost () <= current.GetFCost () && openList [i].GetHCost () < current.GetHCost ()) 
                current = openList [i];

        openList.Remove (current);
        closedList.Add (current);

        if (current == targetNode) {
            RetracePath (startNode, targetNode, ref path);
            return path;
        }

        foreach(Vector2 neighbour in current.neighbors) {
            Node neighbourNode = nodeList.Find (tgt => tgt.nodeID == new Vector2 (neighbour.x, neighbour.y));
            CheckNeighbor(ref neighbourNode, ref current, ref targetNode, ref closedList, ref openList);
        }
    }
    return path;
}

private void CheckNeighbor(ref Node neighborTile, ref Node currentTile, ref Node targetTile, ref List<Node> closedList, ref List<Node> openList){
    if (neighborTile != null) {
        if (!neighborTile.passable || closedList.Contains (neighborTile)) {
        } else {
            int newCostToNeighbor = (int)(currentTile.moveCost + CalculateDistance (currentTile.position, neighborTile.position));
            if (newCostToNeighbor < neighborTile.GetGCost() || !openList.Contains (neighborTile)) {
                neighborTile.SetGCost (newCostToNeighbor);
                neighborTile.SetHCost (CalculateDistance (neighborTile.position, targetTile.position));
                neighborTile.SetParent (currentTile);

                if (!openList.Contains (neighborTile)) 
                    openList.Add (neighborTile);
            }
        }
    }
}

public float CalculateDistance(Vector2 tileA_pos, Vector2 tileB_pos){ 
    float dX = Mathf.Abs (tileB_pos.x - tileA_pos.x); 
    float dY = Mathf.Abs (tileB_pos.y - tileA_pos.y); 
    float shift1 = -(tileA_pos.x + tileA_pos.y); 
    float shift2 = -(tileB_pos.x + tileB_pos.y); 
    float dZ = Mathf.Abs (shift2 - shift1); 
    return Mathf.Max (dX, dY, dZ); 
}

private void RetracePath(Node start, Node end, ref List<Vector2> pathInfo){
    pathInfo = new List<Vector2> ();
    Node current = end;
    while (current != start) {
        pathInfo.Add (current.nodeID);
        current = current.GetParent ();
    }
    pathInfo.Reverse ();
}
私有列表路径fromto(Vector2 startID,Vector2 targetID){
列表路径=新列表();
List closedList=新列表();
List openList=新列表();
Node startNode=nodeList.Find(tgt=>tgt.nodeID==newvector2(startID.x,startID.y));
if(startNode==null)
返回路径;
Node targetNode=nodeList.Find(tgt=>tgt.nodeID==newvector2(targetID.x,targetID.y));
if(targetNode==null)
返回路径;
添加(startNode);
而(openList.Count>0){
节点当前=打开列表[0];
for(inti=1;i
考虑到您在我编写的以下测试程序的注释中显示的
计算状态
方法:(假设您的
Mathf
System.Math
类似)

正如您所看到的,输出是完全古怪的,您可能期望右下角与右上角的距离(0,0)一样远,但事实并非如此。也许您需要重写
calculateInstance
方法

您似乎要计算dX、dY和dZ,这是不可能的,因为您只有2个坐标(
Vector2


编辑:如果未记录“权重”,则可以简单使用毕达哥拉斯计算两点之间的距离:

var dist = Math.Sqrt(Math.Pow(point1.x - point2.x, 2) + Math.Pow(point1.y - point2.y, 2));

您没有说明是否允许对角线移动,但CalculatedInstance的两个例程之一就足够了:

    public static readonly int D = 1;
    public static readonly int D2 = 1;

    public static float CalculateDistance(Vector2 tileA_pos, Vector2 tileB_pos)
    {
        float dX = Math.Abs(tileB_pos.x - tileA_pos.x);
        float dY = Math.Abs(tileB_pos.y - tileA_pos.y);
        return D * (dX + dY);
    }

    public static float CalculateDistanceDiagonalsAllowed(Vector2 tileA_pos, Vector2 tileB_pos)
    {
        float dX = Math.Abs(tileB_pos.x - tileA_pos.x);
        float dY = Math.Abs(tileB_pos.y - tileA_pos.y);
        return D * (dX + dY) + (D2 - 2 * D) * (dX < dY ? dX : dY);
    }
公共静态只读int D=1;
公共静态只读int D2=1;
公共静态浮点计算状态(矢量2 tileA\U pos、矢量2 tileB\U pos)
{
float dX=数学绝对值(tileB_pos.x-tileA_pos.x);
float dY=数学绝对值(tileB_pos.y-tileA_pos.y);
返回D*(dX+dY);
}
公共静态浮点计算标准对角线SALLOWED(矢量2 tileA\u pos,矢量2 tileB\u pos)
{
float dX=数学绝对值(tileB_pos.x-tileA_pos.x);
float dY=数学绝对值(tileB_pos.y-tileA_pos.y);
返回D*(dX+dY)+(D2-2*D)*(dX
其中D是垂直/水平移动的成本,D2是对角线移动的成本-您可能希望根据需要将其设置为1或Sqrt(2)。我假设currentTile.moveCost被用来定义高/低成本的Tile

经过太多的时间(以及一整晚的睡眠),我才能够理解它。这个问题与CheckNeighbor函数有关。新方法如下所示:

private void CheckNeighbor(ref Node neighborTile, ref Node currentTile, ref Node targetTile, ref List<Node> closedList, ref List<Node> openList, bool ignoreMoveCost = false){
    if (neighborTile != null) {
        if (!neighborTile.passable || closedList.Contains (neighborTile)) {
        } else {
            int newCostToNeighbor = (int)((ignoreMoveCost ? 1 : neighborTile.moveCost) + currentTile.GetGCost() + CalculateDistance (currentTile.position, neighborTile.position));
            if (!openList.Contains (neighborTile)) {
                openList.Add (neighborTile);
            } else if (newCostToNeighbor >= neighborTile.GetGCost ()) {
                return;
            }
            neighborTile.SetParent (currentTile);
            neighborTile.SetGCost (newCostToNeighbor);
            neighborTile.SetHCost (CalculateDistance (currentTile.position, neighborTile.position));
        }
    }
}
private void CheckNeighbor(ref-Node neighborTile、ref-Node currentile、ref-Node targetfile、ref-List closedList、ref-List openList、bool ignoreMoveCost=false){
if(neightartile!=null){
如果(!neightartile.passable | | closedList.Contains(neightartile)){
}否则{
int newCostToNeighbor=(int)((ignoreMoveCost?1:neightartile.moveCost)+currentile.GetGCost()+calculateInstance(currentile.position,neightartile.position));
如果(!openList.Contains(neightartile)){
openList.Add(neightartile);
}else if(newCostToNeighbor>=neightartile.GetGCost()){
返回;
}
NeightArtile.SetParent(currentTile);
Neightartile.SetGCost(newCostToNeighbor);
neightartile.SetHCost(CalculateDistance(currentTile.position,neightartile.position));
}
}
}

您已经尝试了什么?你能重现你的问题吗?如果是这样的话,你是否试过调试你的代码,至少试着找出哪里出了问题?我试过处理路径成本和起始位置,但我使用的电路板使用了一些随机生成,因此确定确切的模式可能有点困难。最坏的地方是瓷砖尚可使用但移动成本高的地方。它不是绕过瓷砖,而是穿过瓷砖。瓷砖成本是正确的,它只是产生了一个即兴发挥
    public static readonly int D = 1;
    public static readonly int D2 = 1;

    public static float CalculateDistance(Vector2 tileA_pos, Vector2 tileB_pos)
    {
        float dX = Math.Abs(tileB_pos.x - tileA_pos.x);
        float dY = Math.Abs(tileB_pos.y - tileA_pos.y);
        return D * (dX + dY);
    }

    public static float CalculateDistanceDiagonalsAllowed(Vector2 tileA_pos, Vector2 tileB_pos)
    {
        float dX = Math.Abs(tileB_pos.x - tileA_pos.x);
        float dY = Math.Abs(tileB_pos.y - tileA_pos.y);
        return D * (dX + dY) + (D2 - 2 * D) * (dX < dY ? dX : dY);
    }
private void CheckNeighbor(ref Node neighborTile, ref Node currentTile, ref Node targetTile, ref List<Node> closedList, ref List<Node> openList, bool ignoreMoveCost = false){
    if (neighborTile != null) {
        if (!neighborTile.passable || closedList.Contains (neighborTile)) {
        } else {
            int newCostToNeighbor = (int)((ignoreMoveCost ? 1 : neighborTile.moveCost) + currentTile.GetGCost() + CalculateDistance (currentTile.position, neighborTile.position));
            if (!openList.Contains (neighborTile)) {
                openList.Add (neighborTile);
            } else if (newCostToNeighbor >= neighborTile.GetGCost ()) {
                return;
            }
            neighborTile.SetParent (currentTile);
            neighborTile.SetGCost (newCostToNeighbor);
            neighborTile.SetHCost (CalculateDistance (currentTile.position, neighborTile.position));
        }
    }
}