I keep getting an index out of range exception when testing the pathfinding on the turn based strategy game by Hugo Cardoso. I believe I’ve followed the tutorial exactly as instructed in the videos so im not quite sure what to look for in terms of errors. ive gone back through and checked the mouseworld script and all looks okay.
it looks like your pathfinder is trying to access a node out of the bounds of the GridSystem. The error is occuring in GridSystem.GetGridObject, but it’s actually the Pathfinding GetNeighborList that’s most likely requesting an out of bounds location.
Paste in your Pathfinding.cs script and we’ll take a look.
Hi thank you so much! here it is.
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()
{
//check for duplicate Pathfinding
if (Instance != null)
{
Debug.LogError("There is more that one Pathfinding GameObject" + 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);
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);
}
//remove node from open list and add to closed list
openList.Remove(currentNode);
closedList.Add(currentNode);
foreach(PathNode neighbourNode in GetNeighbourList(currentNode))
{
if(closedList.Contains(neighbourNode))
{
continue;
}
if(!neighbourNode.IsWalkable())
{
closedList.Add(neighbourNode);
continue;
}
int tentativeGCost =
currentNode.GetGCost() + CalculateDistance(currentNode.GetGridPosition(), neighbourNode.GetGridPosition());
if(tentativeGCost < neighbourNode.GetGCost())
{
neighbourNode.SetCameFromPathNode(currentNode);
neighbourNode.SetGCost(tentativeGCost);
neighbourNode.SetHCost(CalculateDistance(neighbourNode.GetGridPosition(), endGridPosition));
neighbourNode.CalculateFCost();
if(!openList.Contains(neighbourNode))
{
openList.Add(neighbourNode);
}
}
}
}
//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> GetNeighbourList(PathNode currentNode)
{
List<PathNode> neighbourList = new List<PathNode>();
GridPosition gridPosition = currentNode.GetGridPosition();
if (gridPosition.x - 1 >= 0)
{
// LeftNode
neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 0));
if (gridPosition.z - 1 >= 0)
{
// BottomLeftNode
neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z - 1));
}
if (gridPosition.z +1 < gridSystem.GetHeight())
{
// TopLeftNode
neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 1));
}
}
if (gridPosition.x + 1 < gridSystem.GetWidth())
{
// RightNode
neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 0));
if (gridPosition.z - 1 >= 0)
{
// BottomRightNode
neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z - 1));
}
if (gridPosition.z +1 < gridSystem.GetHeight())
{
// TopRightNode
neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
}
}
if (gridPosition.z - 1 <= 0)
{
// BottomNode
neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z - 1));
}
if (gridPosition.z +1 < gridSystem.GetHeight())
{
// TopNode
neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z + 1));
}
return neighbourList;
}
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;
}
}
Ok, I traced the code, and I’m not seeing the GetNeighborList having a chance to get out of bounds… To be sure, let’s add a Debug in GetNode that will show us what neighbors we are trying to get:
Now to see what’s going on for this, you’ll need to turn off Collapse in the console. When the Index Out Of Bounds error occurs, it should then land immediately after the Debug of the x,y coordinates that are out of bounds.
This is what shows up in the console after adding the debug. this was with the mouse at grid position x1, z1. i then tried it again at grid position x2,z2 and got the same result with the same numbers in the console.
The starting point should be the location of the character, not the location where the mouse is clicked… Looking at the logs, the starting location appears to be either 2,0, or 0,0…
If it’s 0,0, then the first check x-1 will fail and that round will be skipped…
Then we move on to the next round x+1 in which case x+1 is 1, so we get 1,0, then z-1 fails, and z+1 is 1,1.
Finally, we get to the check for gridPositionz-1 for the bottomnode, and I finally was able to see the error: We should be failing the check, z-1 is -1, so we shouldn’t be adding that node, but…
This only returns true if the gridPosition is < or equal to zero. It’s a hard one to spot, and I looked over this code a dozen times before I spotted it… It was only through figuring out what the starting location was that I was able to zero in on that particular if statement and check it again… it should be:
oh wow honestly i had a feeling it was something small like this as it happens to me a lot! it appears to be working now as the numbers in the grid are changing. just the line isn’t appearing on the grid
The line is from another script. Let’s start by re-watching the lesson on drawing the line. (I’m not in a position to research this tonight as the witching hour approaches). If you are still having trouble with it, paste in the script that draws the line and we’ll take a look tomorrow.
My apologies, i had gizmos turned off. Thank you so much for your help with this!!!
This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.