Hello all! I’ve been fairly successful with finding solutions on my own but this issue has stumped me for the better part of the day, so any help would be appreciated…
On the Pathfinding Obstacles tutorial at the 11:55 mark, the game freezes when attempting to use the DrawLine gizmo to pathfind behind the wall. The gizmo works perfectly when not trying to go around objects. I created the Wall prefab and seem to have all the same boxes ticked as shown in the video, but my player is able to walk through the wall as if there’s no collider, so I’m guessing that’s where the problem lies.
The game also freezes when I attempt to use the GetNode(1,0).SetIsWalkable(false) commands and tried to pathfind around around the two nodes. I skipped this step in the previous tutorial, as I couldn’t get the line to show at the time (forgot to click the Gizmos button) so I tried to implement the code in the following lesson to no avail.
Thanks in advance to anyone who could provide some insight!
Pathfinding code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Pathfinding : MonoBehaviour
{
public static Pathfinding Instance { get; private set; }
private const int MOVE_STRAIGHT_COST = 10;
private const int MOVE_DIAGONAL_COST = 14;
[SerializeField] private Transform gridDebugObjectPrefab;
[SerializeField] private LayerMask obstaclesLayerMask;
private int width;
private int height;
private float cellSize;
private GridSystem<PathNode> gridSystem;
private void Awake()
{
if (Instance != null)
{
Debug.LogError("There's more than one PathFinding! " + transform + " - " + Instance);
Destroy(gameObject);
return;
}
Instance = this;
}
public void Setup(int width, int height, float cellSize)
{
this.width = width;
this.height = height;
this.cellSize = cellSize;
gridSystem = new GridSystem<PathNode>(width, height, cellSize,
(GridSystem<PathNode> g, GridPosition gridPosition) => new PathNode(gridPosition));
gridSystem.CreateDebugObjects(gridDebugObjectPrefab);
//GetNode(1,0).SetIsWalkable(false);
//GetNode(1,1).SetIsWalkable(false);
for (int x = 0; x < width; x++)
{
for (int z = 0; z < height; z++)
{
GridPosition gridPosition = new GridPosition(x, z);
Vector3 worldPosition = LevelGrid.Instance.GetWorldPosition(gridPosition);
float raycastOffsetDistance = 5f;
if (Physics.Raycast(
worldPosition + Vector3.down * raycastOffsetDistance,
Vector3.up,
raycastOffsetDistance * 2,
obstaclesLayerMask))
{
GetNode(x, z).SetIsWalkable(false);
}
}
}
}
public List<GridPosition> FindPath(GridPosition startGridPosition, GridPosition endGridPosition)
{
List<PathNode> openList = new List<PathNode>();
List<PathNode> closedList = new List<PathNode>();
PathNode startNode = gridSystem.GetGridObject(startGridPosition);
PathNode endNode = gridSystem.GetGridObject(endGridPosition);
openList.Add(startNode);
for (int x = 0; x < gridSystem.GetWidth(); x++)
{
for (int z = 0; z < gridSystem.GetHeight(); z++)
{
GridPosition gridPosition = new GridPosition(x, z);
PathNode pathNode = gridSystem.GetGridObject(gridPosition);
pathNode.SetGCost(int.MaxValue);
pathNode.SetHCost(0);
pathNode.CalculateFCost();
pathNode.ResetCameFromPathNode();
}
}
startNode.SetGCost(0);
startNode.SetHCost(CalculateDistance(startGridPosition, endGridPosition));
startNode.CalculateFCost();
while (openList.Count > 0)
{
PathNode currentNode = GetLowestFCostPathNode(openList);
if (currentNode == endNode)
{
//Reached final node
return CalculatePath(endNode);
}
openList.Remove(currentNode);
openList.Add(currentNode);
foreach (PathNode neighborNode in GetNeighborList(currentNode))
{
if (closedList.Contains(neighborNode))
{
continue;
}
if (!neighborNode.IsWalkable())
{
closedList.Add(neighborNode);
continue;
}
int tentativeGCost =
currentNode.GetGCost() + CalculateDistance(currentNode.GetGridPosition(), neighborNode.GetGridPosition());
if (tentativeGCost < neighborNode.GetGCost())
{
neighborNode.SetCameFromPathNode(currentNode);
neighborNode.SetGCost(tentativeGCost);
neighborNode.SetHCost(CalculateDistance(neighborNode.GetGridPosition(), endGridPosition));
neighborNode.CalculateFCost();
if (!openList.Contains(neighborNode))
{
openList.Add(neighborNode);
}
}
}
}
//No Path Found
return null;
}
public int CalculateDistance(GridPosition gridPositionA, GridPosition gridPositionB)
{
GridPosition gridPositionDistance = gridPositionA - gridPositionB;
int xDistance = Mathf.Abs(gridPositionDistance.x);
int zDistance = Mathf.Abs(gridPositionDistance.z);
int remaining = Mathf.Abs(xDistance - zDistance);
return MOVE_DIAGONAL_COST * Mathf.Min(xDistance, zDistance) + MOVE_STRAIGHT_COST * remaining;
}
private PathNode GetLowestFCostPathNode(List<PathNode> pathNodeList)
{
PathNode lowestFCostPathNode = pathNodeList[0];
for (int i = 0; i < pathNodeList.Count; i++)
{
if (pathNodeList[i].GetFCost() < lowestFCostPathNode.GetFCost())
{
lowestFCostPathNode = pathNodeList[i];
}
}
return lowestFCostPathNode;
}
private PathNode GetNode(int x, int z)
{
return gridSystem.GetGridObject(new GridPosition(x,z));
}
private List<PathNode> GetNeighborList(PathNode currentNode)
{
List<PathNode> neighborList = new List<PathNode>();
GridPosition gridPosition = currentNode.GetGridPosition();
if (gridPosition.x - 1 >= 0)
{
//Left
neighborList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 0));
if (gridPosition.z - 1 >= 0)
{
//Left Down
neighborList.Add(GetNode(gridPosition.x - 1, gridPosition.z - 1));
}
if (gridPosition.z + 1 < gridSystem.GetHeight())
{
//Left Up
neighborList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 1));
}
}
if (gridPosition.x + 1 <gridSystem.GetWidth())
{
//Right
neighborList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 0));
if (gridPosition.z - 1 >= 0)
{
//Right Down
neighborList.Add(GetNode(gridPosition.x + 1, gridPosition.z - 1));
}
if (gridPosition.z + 1 < gridSystem.GetHeight())
{
//Right Up
neighborList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
}
}
if (gridPosition.z - 1 >= 0)
{
//Down
neighborList.Add(GetNode(gridPosition.x + 0, gridPosition.z - 1));
}
if (gridPosition.z + 1 < gridSystem.GetHeight())
{
//Up
neighborList.Add(GetNode(gridPosition.x + 0, gridPosition.z + 1));
}
return neighborList;
}
private List<GridPosition> CalculatePath(PathNode endNode)
{
List<PathNode> pathNodeList = new List<PathNode>();
pathNodeList.Add(endNode);
PathNode currentNode = endNode;
while (currentNode.GetCameFromPathNode() != null)
{
pathNodeList.Add(currentNode.GetCameFromPathNode());
currentNode = currentNode.GetCameFromPathNode();
}
pathNodeList.Reverse();
List<GridPosition> gridPositionList = new List<GridPosition>();
foreach (PathNode pathNode in pathNodeList)
{
gridPositionList.Add(pathNode.GetGridPosition());
}
return gridPositionList;
}
}
testing code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Testing : MonoBehaviour
{
[SerializeField] private Unit unit;
private void Start()
{
}
private void Update()
{
if(Input.GetKeyDown(KeyCode.T))
{
GridPosition mouseGridPosition = LevelGrid.Instance.GetGridPosition(MouseWorld.GetPosition());
GridPosition startGridPosition = new GridPosition(0, 0);
List<GridPosition> gridPositionList = Pathfinding.Instance.FindPath(startGridPosition, mouseGridPosition);
for (int i = 0; i < gridPositionList.Count - 1; i++)
{
Debug.DrawLine(
LevelGrid.Instance.GetWorldPosition(gridPositionList[i]),
LevelGrid.Instance.GetWorldPosition(gridPositionList[i + 1]),
Color.white,
10f
);
}
}
}
}