Unity editor crashing on play with no errors

Hello, i am making a basic a* algorithm in unity and my code is below. when i start my game the whole unity editor crashes and i have to start it up again. nothing shows up in the console it just crashes and I don’t know why this is happening?

even if i have an out of bounds or code error it shouldn’t crash the whole editor right?

using UnityEngine;
using System.Collections.Generic;
public class Pathfinding : MonoBehaviour
{
    public Transform seeker;
    public Transform target;
    Grid grid;
    void Awake(){
        grid = GetComponent<Grid>();
    }
    void Start(){
        FindPath(seeker.position, target.position);
    }
    void FindPath(Vector3 startPos, Vector3 targetPos){
        Node startNode = grid.WorldPositionToNode(startPos);
        Node targetNode = grid.WorldPositionToNode(targetPos);

        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++){
                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){
                RetracePath(startNode, targetNode);
                return;
            }

            foreach (Node neighbor in grid.FindNeighborFromNode(currentNode)){
                if(!neighbor.walkable || closedSet.Contains(neighbor)) continue;

                int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
                if(newMovementCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor)){
                    neighbor.gCost = newMovementCostToNeighbor;
                    neighbor.hCost = GetDistance(neighbor, targetNode);
                    neighbor.Parent = currentNode;

                    if(!openSet.Contains(neighbor)){
                        openSet.Add(neighbor);
                    }
                }
            }
        }
    }

    void RetracePath(Node startNode, Node endNode){
        List<Node> path = new();
        Node currentNode = endNode;
        while(currentNode != startNode){
            path.Add(currentNode);
            currentNode = currentNode.Parent;
        }
        path.Reverse();

        grid.path = path;
    }

    int GetDistance(Node nodeA, Node nodeB){
        int x = nodeA.gridX - nodeB.gridX;
        int y = nodeA.gridY - nodeB.gridY;
        if(y > x){
            return 14*y + 10*(x-y);
        }
        return 14*x + 10*(y-x);
    }
}
using UnityEngine;
using System.Collections.Generic;

public class Grid : MonoBehaviour
{
    [SerializeField]
    private LayerMask unwalkableMask;
    [SerializeField] 
    private Vector2 gridWorldSize;
    [SerializeField] 
    private float nodeRadius;
    Node[,] grid;

    private float nodeDiameter;
    private int gridSizeX, gridSizeY;



    public List<Node> path;
    void OnDrawGizmos(){
        Gizmos.DrawWireCube(transform.position, new Vector3(gridWorldSize.x, 1, gridWorldSize.y));

        if(grid != null){
            foreach(Node n in grid){
                Gizmos.color = n.walkable ? Color.green : Color.black;
                if(path != null){
                    if(path.Contains(n)){
                        Gizmos.color = Color.blue;
                    }
                }
                Gizmos.DrawCube(n.worldPosition,Vector3.one * (nodeDiameter - .1f));
            }
        }
    }

    void Awake(){
        nodeDiameter = nodeRadius*2;
        gridSizeX = Mathf.RoundToInt(gridWorldSize.x / nodeDiameter);
        gridSizeY = Mathf.RoundToInt(gridWorldSize.y/nodeDiameter);

        CreateGrid();
    }
    void CreateGrid(){
        grid = new Node[gridSizeX, gridSizeY];
        Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x/2 - Vector3.forward * gridWorldSize.y/2; 

        for(int x = 0; x < gridSizeX; x++){
            for(int y = 0; y < gridSizeY; y++){
                Vector3 worldPoint = worldBottomLeft + Vector3.right * (x * nodeDiameter + nodeRadius) + Vector3.forward * (y * nodeDiameter + nodeRadius);
                bool walkable = !Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask);
                grid[x,y] = new Node(walkable, worldPoint, x, y);
            }
        }
    }

    public List<Node> FindNeighborFromNode(Node node){
        List<Node> neighbors = new();
        for(int x = -1; x < 2; x++){
            for(int y = -1; y < 2; y++){
                if(x==0 && y==0) continue;

                int currentGridX = node.gridX + x;
                int currentGridY = node.gridY + y;

                //bounds check
                if(currentGridX < gridSizeX && currentGridX >= 0 && currentGridY >= 0 && currentGridY < gridSizeY){
                    neighbors.Add(grid[currentGridX,currentGridY]);
                }
            }
        }
        return neighbors;
    }

    public Node WorldPositionToNode(Vector3 worldPosition){
        Vector3 worldBottomLeft = transform.position - Vector3.right * gridWorldSize.x/2 - Vector3.forward * gridWorldSize.y/2; 

        float percentX = (worldPosition.x - worldBottomLeft.x) / gridWorldSize.x;
        float percentY = (worldPosition.z - worldBottomLeft.z) / gridWorldSize.y;

        percentX = Mathf.Clamp01(percentX);
        percentY = Mathf.Clamp01(percentY);

        int x = Mathf.RoundToInt((gridSizeX - 1) * percentX);
        int y = Mathf.RoundToInt((gridSizeY - 1) * percentY);

        return grid[x, y];
    }
}

using UnityEngine;

public class Node
{
    public bool walkable;
    public Vector3 worldPosition;
    public int gridX;
    public int gridY;

    public int gCost;
    public int hCost;
    public Node Parent;

    public Node(bool _walkable, Vector3 _worldPos, int _gridX, int _gridY){
        walkable = _walkable;
        worldPosition = _worldPos;
        gridX = _gridX;
        gridY= _gridY;
    }
    public int fCost{
        get {
            return gCost + fCost;
        }
    }
}

Out of bounds should throw an exception.

Looping is not catch-able and will lock the editor solid.

This is likely what is happening based on your description.

For more backstory, review the halting problem.

Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

Absolutely NOTHING will happen… until your code either:

  • returns from whatever function it is running

  • yields from whatever coroutine it is running

As long as your code is looping, Unity isn’t going to do even a single frame of change. Nothing.

No exceptions.

“Yield early, yield often, yield like your game depends on it… it does!” - Kurt Dekker

Thank you for your insight! my error was a propertys get referencing itself… oops!

as a side note using your own quote is really funny, but i support it lol.

1 Like