IndexOutOfRangeExeption: Index was outside the bounds of the array

Im also having a hard time trying to understand how “Index was outside the bounds of the array” and it only happens at (0,3) of the grid please help.

It means you are trying to access an element in the array that does not exist. It will be in GridSystem on line 60. Position (0, 3) is a little odd. If you share your GridSystem.cs code we can take a look

using System;

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

public class GridSystem

{

private int width;

private int height;

private float cellSize;

private TGridObject[,] gridObjectArray;

public GridSystem(int width, int height, float cellSize, Func<GridSystem<TGridObject>, GridPosition, TGridObject> createGridObject)

{

    this.width = width;

    this.height = height;

    this.cellSize = cellSize;

    gridObjectArray = new TGridObject[width, height];

    for (int x = 0; x < width; x++)

    {

        for (int z = 0; z < height; z++)

        {

            GridPosition gridPosition = new GridPosition(x, z);

            gridObjectArray[x, z] = createGridObject (this, gridPosition);

        }

    }

}

public Vector3 GetWorldPosition(GridPosition gridPosition)

{

    return new Vector3(gridPosition.x, 0, gridPosition.z) * cellSize;

}

public GridPosition GetGridPosition(Vector3 worldPosition)

{

    return new GridPosition(

        Mathf.RoundToInt(worldPosition.x / cellSize),

        Mathf.RoundToInt(worldPosition.z / cellSize)

    );

}

public void CreateDebugObject(Transform debugPrefab)

{

    for (int x = 0; x < width; x++)

    {

        for (int z = 0; z < height; z++)

        {

            GridPosition gridPosition = new GridPosition(x, z);

            Transform debugTransform = GameObject.Instantiate(debugPrefab, GetWorldPosition(gridPosition), Quaternion.identity);

            GridDebugObject gridDebugObject = debugTransform.GetComponent<GridDebugObject>();

            gridDebugObject.SetGridObject(GetGridObject(gridPosition));

        }

    }

}

public TGridObject GetGridObject(GridPosition gridPosition)

{

    return gridObjectArray[gridPosition.x, gridPosition.z];

}

public bool IsValidGridPosition (GridPosition gridPosition)

{

    return gridPosition.x >= 0 &&

           gridPosition.z >= 0 &&

           gridPosition.x < width &&

           gridPosition.z < height;

}

public int GetWidth()

{

    return width;

}

public int GetHeight()

{

    return height;

}

}

OK, this looks fine. I’ve just noticed that the stack trace refers to the pathfinding getting neighbours. It is possible that it’s not bounds checking when it does that. Can you share the GetNeighbourList function from pathfinding, too? See this post to format the code:

Thank you and yes of course.


    private List<PathNode> GetNeighbourList(PathNode currentNode)
    {
        List<PathNode> neighbourList = new List<PathNode>();

        GridPosition gridPosition = currentNode.GetGridPosition();

        if (gridPosition.x - 1 >= 0)
        {
            //Left
            neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 0));
            if (gridPosition.z - 1 >= 0)
            {
                //Left Down
                neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z - 1));
            }
            if (gridPosition.z + 1 < gridSystem.GetHeight())
            {
                //Left Up
                neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 1));
            }

        }

        if (gridPosition.x + 1 < gridSystem.GetWidth())
        {
            //Right
            neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z - 1));
            {
                //Right Down
                neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
            }

            if (gridPosition.z + 1 < gridSystem.GetHeight())
            {
                //Right Up
                neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
            }
        }


        if (gridPosition.z - 1 >= 0)
        { 
            //Down
            neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z - 1));
        }
        if (gridPosition.z + 1 < gridSystem.GetHeight())
        {    
            //Up
            neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z + 1)); 
        }
        return neighbourList;
    }

This part here will break. Here are the issues:

There’s no check if gridPosition.z - 1 will be less than 0. Also, at this point it should be gridPosition.z + 0 anyway


There is also no check here if gridPosition.z + 1 will be greater than height. Also, the //Right Up part is exactly the same code (with a check) and will be checking the same tile. One of them should be gridPosition.z - 1. I can’t remember which


Let me know if you need more than that to solve the problem

I have changed everything and rewatched the pathfinding video to make sure i didn’t make a mistake but I’m still getting the index error.

The problem is still in the same place, though. Share your updated GetNeighbourList(), please. Also include GetNode() just in case

For sure

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)
        {
            //Left
            neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 0));
            if (gridPosition.z - 1 >= 0)
            {
                //Left Down
                neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z - 1));
            }
            if (gridPosition.z + 1 < gridSystem.GetHeight())
            {
                //Left Up
                neighbourList.Add(GetNode(gridPosition.x - 1, gridPosition.z + 1));
            }

        }

        if (gridPosition.x + 1 < gridSystem.GetWidth())
        {
            //Right
            neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 0));
            {
                //Right Down
                neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
            }

            if (gridPosition.z + 1 < gridSystem.GetHeight())
            {
                //Right Up
                neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z - 1));
            }
        }


        if (gridPosition.z - 1 >= 0)
        { 
            //Down
            neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z - 1));
        }
        if (gridPosition.z + 1 < gridSystem.GetHeight())
        {    
            //Up
            neighbourList.Add(GetNode(gridPosition.x + 0, gridPosition.z + 1)); 
        }
        return neighbourList;
    }

Yeah, you still don’t have the second issue fixed:

Nothing here is checking if gridPosition.z + 1 is less than height, so it can (and does) overflow. You also ‘fixed’ the bits you did fix the wrong way round. The second part (// Right Up) is checking if gridPosition.z + 1 is less than height, but then you use gridPosition.z - 1

This is what the right-side checks should look like

if (gridPosition.x + 1 < gridSystem.GetWidth())
{
    //Right
    neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 0));

    if (gridPosition.z - 1 >= 0)
    {
        //Right Down
        neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z - 1));
    }

    if (gridPosition.z + 1 < gridSystem.GetHeight())
    {
        //Right Up
        neighbourList.Add(GetNode(gridPosition.x + 1, gridPosition.z + 1));
    }
}

This here is why I preferred the way I did my neighbours list. This is very verbose and explicit and can be easily analysed, but it also leaves so much room for something to break, and then hides that issue. This is what my GetNeighbourList() looks like (edited because mine contains future work):

private List<PathNode> GetNeighbourList(PathNode currentNode)
{
    var neighbours = new List<PathNode>();
    var gridPosition = currentNode.GetGridPosition();

    for (var z = -1; z <= 1; z++)
    {
        for (var x = -1; x <= 1; x++)
        {
            if (x == 0 && z == 0) continue; // skip self

            var neighbourPosition = new GridPosition(gridPosition.X + x, gridPosition.Z + z);
            if (!_grid.IsValidGridPosition(neighbourPosition)) continue;

            neighbours.Add(GetNode(neighbourPosition));
        }
    }

    return neighbours;
}
1 Like

Thank you so much!
(I hope you have the greatest life ever).

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms