- Home /
Pathfinding Only Working in Editor View
I have two scripts, a Pathfinding script and a GridForPathfinding script. When I am not in the Editor view or looking at the DrawGizmos during play, the Pathfinding script is unable to find the path and I cannot figure out why. I think at this point I have been looking at this for so long and hoping it's just something simple I am overlooking. It has something do with the DrawGizmos, but I am not sure why since it is just reading the path node list. Thank you for any help!
----------------------------------------------------GridForPathfinding Script:-------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridForPathfinding : MonoBehaviour
{
// FORTESTING public Transform playerPlaceholder;
public static GridForPathfinding instance;
public List<Node> path;
public bool onlyDisplayPath;
private Node[,] grid;
private Vector2 gridWorldSize;
public float nodeRadius;
public float nodeDiameter;
private int gridSizeX, gridSizeY;
public LayerMask unWalkableMask;
private void Awake()
{
instance = this;
}
private void OnDrawGizmos()
{
gridWorldSize.x = Maze.instance.iSize.x;
gridWorldSize.y = Maze.instance.iSize.z;
Gizmos.DrawWireCube(Vector3.zero, new Vector3(gridWorldSize.x, 1, gridWorldSize.y));
if (onlyDisplayPath)
{
if(path != null)
{
foreach(Node n in path)
{
Gizmos.color = new Color(0, 1, 0, 0.5f);
Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - 0.1f));
}
}
}
else
{
if (grid != null)
{
// have the pathfinding detect where the Player is
// FORTESTING Node playerNode = NodeFromWorldPoint(playerPlaceholder.position);
foreach (Node n in grid)
{
// visualize what is walkable
Gizmos.color = (n.walkable ? new Color(0, 0, 1, 0.5f) : new Color(1, 0, 0, 0.5f));
if (path != null)
{
if (path.Contains(n))
{
Gizmos.color = new Color(0, 1, 0, 0.5f);
}
}
// FORTESTING
// make Player node a different color
// if (playerNode == n)
// {
// Gizmos.color = new Color(0, 1, 1, 0.5f);
// }
// so the cube is the size of the node, and leave a little room for the walls
Gizmos.DrawCube(n.worldPosition, Vector3.one * (nodeDiameter - 0.1f));
}
}
}
}
public Node NodeFromWorldPoint(Vector3 worldPos)
{
// use a percentage to determine location on the grid
// 0 = far left, 0.5 = center, 1 = right
float percentX = (worldPos.x + gridWorldSize.x / 2) / gridWorldSize.x;
float percentY = 1 -(((worldPos.z + gridWorldSize.y / 2) / gridWorldSize.y));
// clamp between 0 and 1
percentX = Mathf.Clamp01(percentX);
percentY = Mathf.Clamp01(percentY);
// need x and y indexes of grid array
int x = Mathf.RoundToInt((gridSizeX - 1) * percentX);
int y = Mathf.RoundToInt((gridSizeY - 1) * percentY);
return grid[x, y];
}
private void OnEnable()
{
CalculateGridSizeForPathfinding();
}
//calculates the grid size to be navigated
public void CalculateGridSizeForPathfinding()
{
nodeDiameter = nodeRadius * 2;
gridSizeX = Mathf.RoundToInt(Maze.instance.iSize.x/nodeDiameter);
gridSizeY = Mathf.RoundToInt(Maze.instance.iSize.z/ nodeDiameter);
CreateGrid();
}
private void CreateGrid()
{
grid = new Node[gridSizeX, gridSizeY];
Vector3 gridTopLeft = transform.position = new Vector3(-Maze.instance.iSize.x/2, 0.4f, Maze.instance.iSize.z / 2 );
for (int x = 0; x < gridSizeX; x++)
{
for (int y = 0; y < gridSizeY; y++)
{
Vector3 worldPoint = gridTopLeft - Vector3.left * (x * nodeDiameter + nodeRadius) + -Vector3.forward * (y * nodeDiameter + nodeRadius);
// make walkable if there are no collisions in the Unwalkable mask
bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unWalkableMask));
// pass this information into each individual node
grid[x, y] = new Node(walkable, worldPoint, x, y);
}
}
}
public List<Node> GetNeighbors(Node node)
{
List<Node> neighbors = new List<Node>();
// search in a 3x3 block around the node
// x = 0 && y = 0 means we are in the center of that (current Node position)
for(int x = -1; x <= 1; x++)
{
for (int y = -1; y <= 1; y++)
{
if(x == 0 && y == 0)
continue;
int checkX = node.gridX + x;
int checkY = node.gridY + y;
// check if the node is inside of the grid and if so, add to list
if (checkX >= 0 && checkX < gridSizeX && checkY >= 0 && checkY < gridSizeY)
{
neighbors.Add(grid[checkX,checkY]);
}
}
}
return neighbors;
}
public int MaxSize
{
get
{
return gridSizeX * gridSizeY;
}
}
}
----------------------------------------------------Pathfinding Script:-------------------------------------
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Diagnostics;
public class PathFinding : MonoBehaviour
{
public static PathFinding instance;
public GameObject seeker, target;
private void Awake()
{
instance = this;
}
private void Update()
{
if (seeker != null && target != null)
{
StartFindPath();
}
if (Input.GetKeyDown(KeyCode.G))
{
StartFindPath();
}
}
public void StartFindPath()
{
FindPath(seeker.transform.position, target.transform.position);
}
private void FindPath(Vector3 startPos, Vector3 goalPos)
{
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
Node startNode = GridForPathfinding.instance.NodeFromWorldPoint(startPos);
Node targetNode = GridForPathfinding.instance.NodeFromWorldPoint(goalPos);
// list of nodes for Open set
// **I did not implement the Heap because it kept making my editor crash
List<Node> openSet = new List<Node>();
HashSet<Node> closedSet = new HashSet<Node>();
// add the start node to the open set
openSet.Add(startNode);
while(openSet.Count > 0)
{
// need to find the node with the lowest f value
// want to optimize from this nested structure later
Node currentNode = openSet[0];
for (int i = 1; i < openSet.Count; i++)
{
// move to node with lowest f cost
// if fCosts are equal, move to the node with the lowest hCost
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 we have found the path
if(currentNode == targetNode)
{
stopWatch.Stop();
print("path found in: " + stopWatch.ElapsedMilliseconds + " ms");
RetracePath(startNode, targetNode);
return;
}
foreach(Node neighbor in GridForPathfinding.instance.GetNeighbors(currentNode))
{
// if neighbor is not traversable or neighbor is in CLOSED list, skip to next neighbor
if(!neighbor.walkable || closedSet.Contains(neighbor))
{
continue;
}
int newMovementCostToNeighbor = currentNode.gCost + GetDistance(currentNode, neighbor);
// if the gCost is lower than the current node and is not already in the Neighbor list
if (newMovementCostToNeighbor < neighbor.gCost || !openSet.Contains(neighbor))
{
neighbor.gCost = newMovementCostToNeighbor;
// hCost is the distnace from this node to the Goal or Target Node
neighbor.hCost = GetDistance(neighbor, targetNode);
// set parent of neighbor to currentNode so it can point toward it's origin
neighbor.parent = currentNode;
// check if the neighbor is not in the open set, then add
if (!openSet.Contains(neighbor))
{
openSet.Add(neighbor);
}
}
}
}
}
// get path from Start node to Goal/Target node
private void RetracePath(Node startNode, Node endNode)
{
List<Node> path = new List<Node>();
Node currentNode = endNode;
// retrace steps until we reach the start node
while (currentNode != startNode)
{
path.Add(currentNode);
currentNode = currentNode.parent;
}
// ^^ path is currently in reverse, we need to invert that
path.Reverse();
GridForPathfinding.instance.path = path;
}
public void VisualizePath()
{
List<Node> _path = GridForPathfinding.instance.path;
if (_path != null)
{
foreach (Node n in _path)
{
Instantiate(GameManager.instance.waypointDot, n.worldPosition, Quaternion.identity);
}
}
else
{
GameManager.instance.ShowWarning();
}
}
int GetDistance(Node nodeA, Node nodeB)
{
int distX = Mathf.Abs(nodeA.gridX - nodeB.gridX);
int distY = Mathf.Abs(nodeA.gridY - nodeB.gridY);
if(distX > distY)
{
// formula for getting the shortest path between 2 points
return 14 * distY + 10 * (distX - distY);
}
else
{
return 14 * distX + 10 * (distY - distX);
}
}
}
Your answer
Follow this Question
Related Questions
need some help with basic pathfinding with obstacle avoidance 0 Answers
check if an object is reachable 2 Answers
Is it possible to translate a NavMesh at runtime? 2 Answers
How to find the shortest route dynamically based waypoints and their neigbors to reach a destination 2 Answers
Why isn't a Ai Waypoint Spawning??? 0 Answers