NullRefException when adding value & key to a dictionary (Breadth first search)

Hi this is my first post here, I am new to coding.

I am making a tile-based tower defense game and using BFS to create enemy pathfinding. I get a NRE at runtime and it highlights the enemy object pool gameobject the script is attatched to.

public class Pathfinder : MonoBehaviour

{
    [SerializeField] Vector2Int startCoordinates, endCoordinates;
    Vector2Int[] directions = {Vector2Int.right, Vector2Int.left, Vector2Int.up, Vector2Int.down};
    Node startNode, endNode;
    [SerializeField] Node currentSearchNode;
    GridController gridController;
    Dictionary<Vector2Int, Node> gridDictionary, reachedDictionary;
    Queue<Node> frontier = new Queue<Node>();

    void Start()
    {
        gridController = FindAnyObjectByType<GridController>();
        if (gridController != null )
        {
            gridDictionary = gridController.GridDictionary;
        }
        startNode = new Node(startCoordinates, true);
        endNode = new Node(endCoordinates, true);
        BreadthFirstSearch();
    }

    void BreadthFirstSearch()
    {
        bool isRunning = true;
        frontier.Enqueue(startNode);
        reachedDictionary.Add(startCoordinates, startNode); // This line is throwing the error
        while (frontier.Count > 0 && isRunning)
        {
            currentSearchNode = frontier.Dequeue();
            currentSearchNode.bIsExplored = true;
            ExploreNeighbors();
            if (currentSearchNode.vCoordinates == endCoordinates)
            {
                isRunning = false;
            }
        }
    }

    void ExploreNeighbors()
    {
        List<Node> neighbors = new List<Node>();
        foreach (Vector2Int direction in directions)
        {
            Vector2Int neighborCoordinates = currentSearchNode.vCoordinates + direction;
            if (gridDictionary.ContainsKey(neighborCoordinates))
            {
                neighbors.Add(gridDictionary[neighborCoordinates]);
            }
        }
        foreach (Node neighbor in neighbors)
        {
            if (!reachedDictionary.ContainsKey(neighbor.vCoordinates) && neighbor.bIsTraversable)
            {
                reachedDictionary.Add(neighbor.vCoordinates, neighbor);
                frontier.Enqueue(neighbor);
            }
        }
    }
}

Sorry if this is messy, so is my project lol

Exceptions come with a stack trace unless you’ve disabled that functionality. Tell us where in the code that the exception is being thrown, i.e. what file and which line (in fact, it’s most useful to just paste the entire stack trace), and show the full file that is listed. For any code you post, include the using statements at the top of the file. These are conspicuously missing in your code that uses MonoBehaviour, so this is not the complete file.

1 Like

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

public class Pathfinder : MonoBehaviour
{
    GridController gridController;
    [SerializeField] Vector2Int startCoordinates, endCoordinates;
    Vector2Int[] directions = {Vector2Int.right, Vector2Int.left, Vector2Int.up, Vector2Int.down};
    Node startNode, endNode;
    [SerializeField] Node currentSearchNode;
    Dictionary<Vector2Int, Node> gridDictionary, reachedDictionary;
    Queue<Node> frontier = new Queue<Node>();
    void Awake()
    {
    }
    void Start()
    {
        gridController = FindAnyObjectByType<GridController>();
        if (gridController != null )
        {
            gridDictionary = gridController.GridDictionary;
        }
        startNode = new Node(startCoordinates, true);
        endNode = new Node(endCoordinates, true);
        BreadthFirstSearch();
    }
    void BreadthFirstSearch()
    {
        bool isRunning = true;
        frontier.Enqueue(startNode);
        reachedDictionary.Add(startCoordinates, startNode); // <--- This line is throwing error
        while (frontier.Count > 0 && isRunning)
        {
            currentSearchNode = frontier.Dequeue();
            currentSearchNode.bIsExplored = true;
            ExploreNeighbors();
            if (currentSearchNode.vCoordinates == endCoordinates)
            {
                isRunning = false;
            }
        }
    }
    void ExploreNeighbors()
    {
        List<Node> neighbors = new List<Node>();
        foreach (Vector2Int direction in directions)
        {
            Vector2Int neighborCoordinates = currentSearchNode.vCoordinates + direction;
            if (gridDictionary.ContainsKey(neighborCoordinates))
            {
                neighbors.Add(gridDictionary[neighborCoordinates]);
            }
        }
        foreach (Node neighbor in neighbors)
        {
            if (!reachedDictionary.ContainsKey(neighbor.vCoordinates) && neighbor.bIsTraversable)
            {
                reachedDictionary.Add(neighbor.vCoordinates, neighbor);
                frontier.Enqueue(neighbor);
            }
        }
    }
}

Maybe this will add a little clarity?

Having noticed your comment in the code (not the preferred way to indicate what’s throwing an error, instead post the line number outside the code block), you haven’t constructed the reachedDictionary object. You need to create objects one way or another, otherwise they will be null. Use a constructor to create the object, preferably inside Start or as a field initializer as you’re doing with the queue.

2 Likes

Thank you that did the trick, thanks also for the etiquette tips. Saved me a headache over such a small oversight :sweat_smile: