0

Я пытаюсь реализовать алгоритм AStars для своей игры. Суть алгоритма заключаетсяв поиске пути по графу

Граф я создал, но теперь я не могу подключить сам алгоритм

Это класс Astars. Есть ещё класс Node, но там ничего такого, просто конструктор и набор параметров для каждой из вершин

public class Astar
{
    List<List<Node>> Grid;  //нужно для алгоритма. Это просто разметка карты на вершины графа
    int GridRows
    {
        get
        {
           return Grid[0].Count;
        }
    }
    int GridCols
    {
        get
        {
            return Grid.Count;
        }
    }
public Astar(List&lt;List&lt;Node&gt;&gt; grid)   //конструктор 
{
    Grid = grid;
}

public Stack&lt;Node&gt; FindPath(Vector2 Start, Vector2 End) //сам алгоритм поиска пути
{
    Node start = new Node(new Vector2((int)(Start.x/Node.NODE_SIZE), (int) (Start.y/Node.NODE_SIZE)), true);
    Node end = new Node(new Vector2((int)(End.x / Node.NODE_SIZE), (int)(End.y / Node.NODE_SIZE)), true);

    Stack&lt;Node&gt; Path = new Stack&lt;Node&gt;();
    List&lt;Node&gt; OpenList = new List&lt;Node&gt;();
    List&lt;Node&gt; ClosedList = new List&lt;Node&gt;();
    List&lt;Node&gt; adjacencies;
    Node current = start;

    // add start node to Open List
    OpenList.Add(start);

    while(OpenList.Count != 0 &amp;&amp; !ClosedList.Exists(x =&gt; x.Position == end.Position))
    {
        current = OpenList[0];
        OpenList.Remove(current);
        ClosedList.Add(current);
        adjacencies = GetAdjacentNodes(current);


        foreach(Node n in adjacencies)
        {
            if (!ClosedList.Contains(n) &amp;&amp; n.Walkable)
            {
                if (!OpenList.Contains(n))
                {
                    n.Parent = current;
                    n.DistanceToTarget = Math.Abs(n.Position.x - end.Position.x) + Math.Abs(n.Position.y - end.Position.y);
                    n.Cost = n.Weight + n.Parent.Cost;
                    OpenList.Add(n);
                    OpenList = OpenList.OrderBy(node =&gt; node.F).ToList&lt;Node&gt;();
                }
            }
        }
    }

    // construct path, if end was not closed return null
    if(!ClosedList.Exists(x =&gt; x.Position == end.Position))
    {
        return null;
    }

    // if all good, return path
    Node temp = ClosedList[ClosedList.IndexOf(current)];
    if (temp == null) return null;
    do
    {
        Path.Push(temp);
        temp = temp.Parent;
    } while (temp != start &amp;&amp; temp != null) ;
    return Path;
}

private List&lt;Node&gt; GetAdjacentNodes(Node n)
{
    List&lt;Node&gt; temp = new List&lt;Node&gt;();

    int row = (int)n.Position.y;
    int col = (int)n.Position.x;

    if(row + 1 &lt; GridRows)
    {
        temp.Add(Grid[col][row + 1]);
    }
    if(row - 1 &gt;= 0)
    {
        temp.Add(Grid[col][row - 1]);
    }
    if(col - 1 &gt;= 0)
    {
        temp.Add(Grid[col - 1][row]);
    }
    if(col + 1 &lt; GridCols)
    {
        temp.Add(Grid[col + 1][row]);
    }

    return temp;
}

}

И есть скрипт для моего юнита

public class warrior : MonoBehaviour
{
Astar astar; //создаю объект класса Astar, чтобы потом вызывать FindPath

private navigationSquare square; //это нужно для нахождения конечной точки public GameObject grid; //на этом объекте висит скрипт navigationSquare Stack<Node> path = new Stack<Node>(); //стек с путем, который вернет функция astar.FindPath(...);

void Start() { square = grid.GetComponent<navigationSquare>(); //получаю доступ к скрипту Debug.Log(square.end.x); astar = new Astar(makeGrid.getGraph()); //инициализирую объект при помощи конструктора //makeGrid.getGraph() вернет List<List<Node>> карту графов }

// Update is called once per frame void Update() { if(square.canGo == true){ Vector2 pos_start = new Vector2(transform.position.x, transform.position.y); //начальная позиция юнита Vector2 pos_end = new Vector2(square.end.x, square.end.y); //и место, куда он должен придти path = astar.FindPath(pos_start, pos_end); printPath(); //её реализация не важна
}

} }

в итоге я получаю вот такой error введите сюда описание изображения

Я так понимаю, что у меня ошибка в том, что я как-то неправильно создаю объект класса Astar или что я неправильно вызываю его методы

Уже несколько дней ломаю голову над этими NullReferenceException....

Научите неразумного, добрые люди(

102 строка adjacencies = GetAdjacentNodes(current); 145 строка if(row + 1 < GridRows) 29 строка path = astar.FindPath(pos_start, pos_end);

Arlen
  • 21
  • 7
  • Подсказка OpenList.OrderBy - здесь с помощью Linq вы пересоздаете список, это медленно и кушает память, попробуйте вместо этого использовать метод List.Sort(). Это не решит вашу проблему, но улучшит производительность кода. По поводу null - все просто, метод GetAdjacentNodes получает null на вход в качестве аргумента, и при попытке обратиться к этому null (n.Position), вы получаете искомое исключение. – aepot Feb 11 '21 at 09:01
  • А, GridRows, ну тогда возможно скрипт выполняется до того как вы создали поле, попробуйте защитить геттеры return Grid[0].Count; замените на return GridCols > 0 ? Grid[0]?.Count ?? 0 : 0;, а return Grid.Count; на return Grid?.Count ?? 0; – aepot Feb 11 '21 at 09:10

0 Answers0