A * Pathfinding не работает должным образом? - PullRequest
0 голосов
/ 10 апреля 2020

Это моя первая публикация о переполнении стека после нескольких лет его просмотра! Я надеялся, что кто-нибудь поможет мне понять, что случилось с моим A * определением пути. Это работает иногда, особенно на узлах, которые находятся на заданном c краю моей карты.

Чтобы дать некоторый контекст, я использую гексагональную сетку и порождаю врагов по краю карты, и их цель - центр доски. Это работает для врагов, порожденных вдоль нижнего ряда, однако все когда-либо грани это или временно, или не работает вообще. (пи c игрового поля)

Я пробовал различные функции Heuristi c, и я следовал этому уроку: https://web.archive.org/web/20170707190212/http: // www.policyalmanac.org/games/aStarTutorial.htm

И вот где я получил свою функцию Heuristi c от: http://3dmdesign.com/development/hexmap-coordinates-the-easy-way

Я надеюсь, что кто-то может помочь,

Спасибо!

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

public class Search
{
    public Node[,] graph = GameBoardGeneration.Instance.Graph; //The entire game board representation as a 2D array of Nodes.


    public List<Node> path; //The Chosen path after the search has occured
    private List<Node> openNodes;
    private List<Node> closedNodes;
    private int m_straightCost = 10;
    private int m_diagonalCost = 8;



    //public float unitAggression;

    //////////////////////////////////////////////////// NEW IMPLEMENTATION

    public void StartSearch(Node _startNode, Node _endNode)
    {
        path = new List<Node>();
        openNodes = new List<Node>();
        closedNodes = new List<Node>();

        openNodes.Add(_startNode);
        foreach(Node _adjacentNode in _startNode.adjecant)
        {
            openNodes.Add(_adjacentNode);
            _adjacentNode.searchData.parentNode = _startNode;
        }

        openNodes.Remove(_startNode);
        closedNodes.Add(_startNode);
        Node _currentNode;

        while (openNodes.Count > 0)
        {
            //Lowest F cost out of all of the nodes in openNodes.
            float _lowestF = Mathf.Infinity;
            _currentNode = null;
            foreach(Node _node in openNodes)
            {
                if (_node.searchData.F < _lowestF)
                {
                    _currentNode = _node;
                    _lowestF = _node.searchData.F;
                }
            }
            openNodes.Remove(_currentNode);
            closedNodes.Add(_currentNode);

            if(_currentNode == _endNode)
            {
                break;
            }
            foreach (Node _adjacentNode in _currentNode.adjecant)
            {
                if (closedNodes.Contains(_adjacentNode))
                {
                    break;
                }
                else if (!openNodes.Contains(_adjacentNode))
                {
                    openNodes.Add(_adjacentNode);
                    _adjacentNode.searchData.parentNode = _currentNode;
                    _adjacentNode.searchData.G = _adjacentNode.searchData.parentNode.searchData.G + calculateDirectionalCost(_currentNode, _adjacentNode);
                    _adjacentNode.searchData.H = hexagonalHeuristicCost(_adjacentNode, _endNode) * m_straightCost;
                    _adjacentNode.searchData.F = _adjacentNode.searchData.G + _adjacentNode.searchData.H;
                }
                else if (openNodes.Contains(_adjacentNode))
                {
                    //If G cost of adjacent is LOWER than G cost of current
                    if(_adjacentNode.searchData.G < _currentNode.searchData.G + calculateDirectionalCost(_currentNode,_adjacentNode))
                    {
                        _adjacentNode.searchData.parentNode = _currentNode;
                        _adjacentNode.searchData.G = _adjacentNode.searchData.parentNode.searchData.G + calculateDirectionalCost(_currentNode, _adjacentNode);
                        _adjacentNode.searchData.F = _adjacentNode.searchData.G + _adjacentNode.searchData.H;
                    }
                }
            }
        }



        if(openNodes.Count == 0)
        {
            Debug.Log("Pathfinding Failed");
        }
        else
        {
            //Work out the path now
            _currentNode = _endNode;
            Node _parentNode = _endNode.searchData.parentNode;
            path.Add(_currentNode);
            while (_currentNode != _startNode)
            {
                _parentNode = _currentNode.searchData.parentNode;
                if (_parentNode == null)
                {
                    Debug.Log("FAILED");
                }
                path.Add(_parentNode);
                _currentNode = _parentNode;
            }
            path.Reverse();
        }


    }

    private int calculateDirectionalCost(Node _fromNode, Node _toNode)
    {
        if(_fromNode.y == _toNode.y)
        {
            //Nodes are straight next to eachother.
            return m_straightCost;
        }
        else
        {
            //Nodes are diagonal across from eachother.
            return m_diagonalCost;
        }
    }

    private int hexagonalHeuristicCost(Node _fromNode, Node _endNode)
    {
        int _xDifference = Mathf.Abs(_fromNode.x - _endNode.x);
        int _yDifference = Mathf.Abs(_fromNode.y - _endNode.y);
        int _xyDifference = Mathf.Abs(_xDifference - _yDifference);

        //return Mathf.Max(_xDifference, Mathf.Max(_yDifference, _xyDifference)); //Returns the largest.

        return Mathf.RoundToInt(Vector3.Distance(_fromNode.hex.transform.position, _endNode.hex.transform.position));  //Absolute Distance between two nodes.



    }
}

...