8 Directional Pathfinding (A*) - Inconsistently Finding Path

Newbie here so sorry if I don't describe the problem well.

I'm attempting to create an 8 directional pathfinding script. I've followed the majority of a tutorial but wanted to change it up to work in a way that's easier for me to understand.

The GetNeighbours method works in 4 directions but not diagonally. I'm using a Dictionary to index the x and y value in a node (cell). I know this is not efficient but it's easier for me to understand and more flexible.

Anyway, the pathing works only sometimes. Seems like I can't get the neighbouring cells whenever I need to move to the top or left row. If I put holes in the tilemap it also messes up the pathing but only when I go behind the holes sometimes, see image: not working:

1

working:

2

Any help would be amazing!

    public List<Node> GetNeighbours(Node node)
    {
        List<Node> neighbours = new List<Node>();
        int checkX = node.gridX;
        int checkY = node.gridY;

        //left
        if (nodes.ContainsKey(new Vector2Int(checkX-1, checkY))) 
        {
            neighbours.Add(nodes[new Vector2Int(checkX-1, checkY)]);
        }
        //right
        if (nodes.ContainsKey(new Vector2Int(checkX +1, checkY)))
        {
            neighbours.Add(nodes[new Vector2Int(checkX + 1, checkY)]);
        }
        //up
        if (nodes.ContainsKey(new Vector2Int(checkX, checkY + 1)))
        {
            neighbours.Add(nodes[new Vector2Int(checkX, checkY +1)]);
        }
        //down
        if (nodes.ContainsKey(new Vector2Int(checkX, checkY - 1)))
        {
            neighbours.Add(nodes[new Vector2Int(checkX, checkY - 1)]);
        }

        //top left
        if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)) && nodes.ContainsKey(new Vector2Int(checkX, checkY + 1)) && nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)));
        {
            neighbours.Add(nodes[new Vector2Int(checkX -1, checkY + 1)]);
        }
        //top right
        if(nodes.ContainsKey(new Vector2Int(checkX + 1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY + 1)) && nodes.ContainsKey(new Vector2Int(checkX + 1, checkY + 1)))
        {
            neighbours.Add(nodes[new Vector2Int(checkX + 1, checkY + 1)]);
        }
        //bottom left
        if(nodes.ContainsKey(new Vector2Int(checkX-1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY -1 )) && nodes.ContainsKey(new Vector2Int(checkX - 1, checkY - 1)))
        {
           neighbours.Add(nodes[new Vector2Int(checkX - 1, checkY - 1)]);
        }
        //bottomright
        if (nodes.ContainsKey(new Vector2Int(checkX +1, checkY)) && nodes.ContainsKey(new Vector2Int(checkX, checkY -1)) && nodes.ContainsKey(new Vector2Int(checkX + 1, checkY - 1)))
        {
            neighbours.Add(nodes[new Vector2Int(checkX + 1, checkY - 1)]);
        }
        
        // Debug.Log("number of neighbours added is: " + neighbours.Count);
        return neighbours;
    }

The Pathfinding Class

public class Pathfiding
{
    public static List<Vector2Int> FindPath(Grid grid, Vector2Int startPos, Vector2Int endPos)
    {
        List<Node> nodes_path = _ImpFindPath(grid, startPos, endPos);

        if (!grid.nodes.ContainsKey(startPos) || !grid.nodes.ContainsKey(endPos))
        {
            return null;
        }
        else
        {
            //get nodes and return a list of points
            List<Vector2Int> ret = new List<Vector2Int>();

            if (nodes_path != null)
            {
                foreach (Node n in nodes_path)
                {
                    ret.Add(new Vector2Int(n.gridX, n.gridY)); //load all nodes to check
                }
            }
            return ret;
        }
    }//end FindPath////

    private static List<Node> _ImpFindPath(Grid grid, Vector2Int startPos, Vector2Int endPos)
    {
        Node startNode;
        Node targetNode;

      
            startNode = grid.nodes[startPos];
            targetNode = grid.nodes[endPos];
        

        List<Node> openSet = new List<Node>();
        HashSet<Node> closedSet = new HashSet<Node>();

        openSet.Add(startNode);


        while (openSet.Count > 0)
        {
            Node currentNode = openSet[0];
            for (int i = 1; i < openSet.Count; i++)
            {
                //only check nodes with better f costs
                if (openSet[i].fCost < currentNode.fCost || openSet[i].fCost == currentNode.fCost && openSet[i].hCost < currentNode.hCost)
                {
                    currentNode = openSet[i];
                }
            }

            openSet.Remove(currentNode);
            closedSet.Add(currentNode);

            if (currentNode == targetNode)
            {
                return RetracePath(grid, startNode, targetNode);
            }

            foreach (Node neighbour in grid.GetNeighbours(currentNode))
            {
                if (neighbour.walkPenalty <= 0 || closedSet.Contains(neighbour))
                {
                    continue;
                }

                int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour) * (int)(10.0f * neighbour.walkPenalty);

                if (newMovementCostToNeighbour < neighbour.gCost || !openSet.Contains(neighbour))
                {
                    neighbour.gCost = newMovementCostToNeighbour;
                    neighbour.hCost = GetDistance(neighbour, targetNode);
                    neighbour.parent = currentNode;

                    if (!openSet.Contains(neighbour))
                        openSet.Add(neighbour);
                }
            }
        }

        return null;
    }

There are three errors in the //top left condition:

  1. There should be no semicolon at the end of the if statement. It makes the if statement useless and even worse it always executes the block below. So a diagonal path option towards top-left is always present.

  2. Once you fix the first error, you need to change checkY - 1 to checkY in the first predicate of the if condition.

  3. And you need to change checkY - 1 to checkY + 1 in the last predicate.

//top left
if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY)) &&
    nodes.ContainsKey(new Vector2Int(checkX, checkY + 1)) &&
    nodes.ContainsKey(new Vector2Int(checkX - 1, checkY + 1)))
{
  neighbours.Add(nodes[new Vector2Int(checkX -1, checkY + 1)]);
}

It would be even better to use TryGetValue to avoid one more struct construction and lookup:

//top left
if (nodes.ContainsKey(new Vector2Int(checkX - 1, checkY)) &&
    nodes.ContainsKey(new Vector2Int(checkX, checkY + 1)) &&
    nodes.TryGetValue(new Vector2Int(checkX - 1, checkY + 1), out var n))
{
  neighbours.Add(n);
}

I am not sure if these are all the direct errors in your code, just try it.

There is one more indirect error related to the diagonal movement. I do not understand why you need to check the 4-neighborhood path along with the diagonal check. If the 4-neighbors must be present anyhow, why do you explicitly add the diagonal movement? Or is it another error, that for diagonal movement the non-diagonal predicates should be actually omitted?