A *寻路问题

时间:2017-08-15 18:41:17

标签: debugging unity3d path-finding a-star

我正在使用inScope Studio的塔防教程作为我正在制作的游戏的支架,并设置了一个工作的A *探路者从头到尾,但是我在设置时遇到了麻烦攻击单位的动态寻路。

触发时,设备应生成从其位置到目标位置的路径,但由于某种原因,路径寻找脚本无法返回路径。调试时我注意到该算法无法检测推导出最佳路径,并且最终将所有节点都放在关闭列表中。

这是我的A *脚本和相关代码:

using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public static class AStar
{
/// <summary>
/// A dictionary for all nodes in the game
/// </summary>
private static Dictionary<Point, Node> nodes;

/// <summary>
/// Creates a node for each tile in the game
/// </summary>
private static void CreateNodes()
{
    //Instantiates the dicationary
    nodes = new Dictionary<Point, Node>();

    //Run throughm all the tiles in the game
    foreach (TileScript tile in LevelManager.Instance.Tiles.Values)
    {
        //Adds the node to the node dictionary
        nodes.Add(tile.GridPosition, new Node(tile));
    }
}

/// <summary>
/// Generates a path with the A* algothithm
/// </summary>
/// <param name="start">The start of the path</param>
public static Stack<Node> GetPath(Point start, Point goal)
{
    if (nodes == null) //If we don't have nodes then we need to create them
    {
        CreateNodes();
    }

    //Creates an open list to be used with the A* algorithm
    HashSet<Node> openList = new HashSet<Node>();

    //Creates an closed list to be used with the A* algorithm
    HashSet<Node> closedList = new HashSet<Node>();

    // 1,2,3

    Stack<Node> finalPath = new Stack<Node>();

    //Finds the start node and creates a reference to it called current node
    Node currentNode = nodes[start];

    //1. Adds the start node to the OpenList
    openList.Add(currentNode);

    while (openList.Count > 0)//Step 10
    {
        //2. Runs through all neighbors 
        for (int x = -1; x <= 1; x++)
        {
            for (int y = -1; y <= 1; y++)
            {
                Point neighbourPos = new Point(currentNode.GridPosition.X - x, currentNode.GridPosition.Y - y);

                if (LevelManager.Instance.InBounds(neighbourPos) && LevelManager.Instance.Tiles[neighbourPos].Walkable && neighbourPos != currentNode.GridPosition)
                {
                    //Sets the initial value of g to 0
                    int gCost = 0;

                    if (Math.Abs(x - y) == 1)//Check is we need to score 10
                    {
                        gCost = 10;
                    }
                    else //Scores 14 if we are diagonal
                    {
                        if(!ConnectedDiagonally(currentNode, nodes[neighbourPos]))
                        {
                            continue;
                        }
                        gCost = 14;
                    }

                    //3. Adds the neighbor to the open list
                    Node neighbour = nodes[neighbourPos];

                    Debug.Log (gCost);

                    if (openList.Contains(neighbour))
                    {
                        if (currentNode.G + gCost < neighbour.G)//Step 9.4
                        {
                            neighbour.CalcValues(currentNode, nodes[goal], gCost);
                        }
                    }
                    else if (!closedList.Contains(neighbour))//9.1
                    {
                        openList.Add(neighbour); //9.2
                        neighbour.CalcValues(currentNode, nodes[goal], gCost);//9.3

                    }

                }
            }
        }

        //5. & 8. Moves the current node from the open list to the closed list
        openList.Remove(currentNode);
        closedList.Add(currentNode);

        if (openList.Count > 0)//STEP 7.
        {
            //Sorts the list by F value, and selects the first on the list
            currentNode = openList.OrderBy(n => n.F).First();
        }

        Debug.Log ("currentNode: " + currentNode.GridPosition.X + ", " + currentNode.GridPosition.Y + "\ngoal: " + nodes[goal].GridPosition.X + ", " + nodes[goal].GridPosition.Y);

        if (currentNode == nodes[goal])
        {
            while (currentNode.GridPosition != start)
            {
                finalPath.Push(currentNode);
                currentNode = currentNode.Parent;
            }

            break;
        }
    }


    return finalPath;
}

private static bool ConnectedDiagonally(Node currentNode, Node neighbor)
{
    Point direction = neighbor.GridPosition - currentNode.GridPosition;

    Point first = new Point (currentNode.GridPosition.X + direction.X, currentNode.GridPosition.Y + direction.Y);

    Point second = new Point (currentNode.GridPosition.X, currentNode.GridPosition.Y + direction.Y);

    if (LevelManager.Instance.InBounds (first) && !LevelManager.Instance.Tiles [first].Walkable) 
    {
        return false;
    }

    if (LevelManager.Instance.InBounds (second) && !LevelManager.Instance.Tiles [second].Walkable) {
        return false;
    }

    return true;
}
}

private void GeneratePathToTarget()
{
    Point targetLocation = new Point (target.transform.parent.GetComponent<TileScript> ().GridPosition.X, target.transform.parent.GetComponent<TileScript> ().GridPosition.Y);

    path = AStar.GetPath (this.GridPosition, targetLocation);
}

private void OnTriggerEnter2D(Collider2D other)
{
    if (other.tag == "Tower" && Attacker) 
    {
        target = other.gameObject;

        GeneratePathToTarget ();
    }
}

奇怪的是,我上周成功地让它工作了,但由于大量的github失败,我不得不重写所有内容。

0 个答案:

没有答案