How is this working without neighbors.Clear()?

When I use the code from the lesson, the first time my scripts run they find a path just fine. However, once I placed a tower anywhere on my board (whether it was in the path or not) my path just became the start node and end node, with no other nodes in between. Using debug statements, I found out that somehow my destination node’s connectedTo value would always be the same as my start node. After more debugging, I found that every node had the start node as it’s connectedTo and that this was because my ExploreNeighbors method was looping through all my “neighbors” tiles. Once I added neighbors.Clear(); to my BredthFirstSearch method, everything started working.

So… How was this working in the lesson without that statement?

Here’s my current code for Pathfinder.cs (with a few debug lines I haven’t taken out yet)

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

public class Pathfinder : MonoBehaviour
{
    [SerializeField] Vector2Int startCoords;
    [SerializeField] Vector2Int destinationCoords;
    //[SerializeField] GameObject testCube;

    Node startNode;
    Node currentSearchNode;
    Node destinationNode;

    Queue<Node> frontier = new Queue<Node>();
    Dictionary<Vector2Int, Node> reached = new Dictionary<Vector2Int, Node>();
    
    Vector2Int[] directions = { Vector2Int.right, Vector2Int.left, Vector2Int.up, Vector2Int.down};
    List<Node> neighbors = new List<Node>();
    GridManager gridManager;
    Dictionary<Vector2Int, Node> grid = new Dictionary<Vector2Int, Node>();
    
    void Awake()
    {
        gridManager = FindObjectOfType<GridManager>();
        if (gridManager != null)
        {
            grid = gridManager.Grid;
        }
    }

    void Start()
    {
        startNode = grid[startCoords];
        destinationNode = grid[destinationCoords];

        GetNewPath();
    }

    public List<Node> GetNewPath()
    {
        gridManager.ResetNodes();
        BredthFirstSearch();
        return BuildPath();       
    }

    void BredthFirstSearch()
    {
        frontier.Clear();
        reached.Clear();
        neighbors.Clear();
        
        bool isRunning = true;

        frontier.Enqueue(startNode);
        reached.Add(startCoords, startNode);

        while (frontier.Count > 0 && isRunning)
        {
            currentSearchNode = frontier.Dequeue();
            currentSearchNode.isExplored = true;
            ExploreNeighbors();

            if (currentSearchNode.nodeCoordinates == destinationCoords)
            {
                isRunning = false;
            }
        }

    }

    void ExploreNeighbors()
    {
        foreach (Vector2Int direction in directions)
        {
            Vector2Int newCoords = direction + currentSearchNode.nodeCoordinates;

            if (grid.ContainsKey(newCoords))
            {
                neighbors.Add(grid[newCoords]);
            }

            foreach (Node neighbor in neighbors)
            {
                if (!reached.ContainsKey(neighbor.nodeCoordinates) && neighbor.isWalkable)
                {
                    neighbor.connectedTo = currentSearchNode;
                    reached.Add(neighbor.nodeCoordinates, neighbor);
                    frontier.Enqueue(neighbor);
                    //Added this to get a visualization of how explore neighbors was working.
                    // Vector3 cubePosition = new Vector3(neighbor.connectedTo.nodeCoordinates.x *10, 0.5f, neighbor.connectedTo.nodeCoordinates.y *10);
                    // Instantiate(testCube, cubePosition, Quaternion.identity);
                }
            }

        }
    }
    List<Node> BuildPath()
    {
        List<Node> path = new List<Node>();
        Node pathNode = destinationNode;

        path.Add(pathNode);
        pathNode.isPath = true;

        while (pathNode.connectedTo != null)
        {
            pathNode = pathNode.connectedTo;
            path.Add(pathNode);
            pathNode.isPath = true;
        }

        path.Reverse();
        return path;
    }

    public bool WillBlockPath(Vector2Int coordinates)
    {
        if (grid.ContainsKey(coordinates))
        {
            bool previousState = grid[coordinates].isWalkable;
            
            grid[coordinates].isWalkable = false;
            List <Node> newPath = GetNewPath();
            grid[coordinates].isWalkable = previousState;
            
            if (newPath.Count <= 1)
            {
                GetNewPath();
                return true;
            }
        }
        
        return false;
        
    }

}

Nevermind… I see that somehow I declared my ‘neighbors’ variable outside of the ExploreNeighbors method. Putting that back within the method eliminates the need to have it cleared.

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms