Error idk how to fix

im watching this tut “https://www.youtube.com/watch?v=Q16audEXrcI&list=PLVsTSlfj0qsWEJ-5eMtXsYp03Y9yF1dEn&index=5
and i have a error i never have seen before
IndexOutOfRangeException: Index was outside the bounds of the array.
Chunk.CheckVoxel (UnityEngine.Vector3 pos) (at Assets/scripts/Chunk.cs:102)

line 102 has return world.blocktypes[voxelMap [x, y, z]].isSolid;

so

OK so either

world.blocktypes [ some value ]
or
voxelmap [ x, y, z ]

is not valid, your first job is to break that up to find out which

so, check the values of x, y and z
then check the size of voxelmap for those values
finally whatever voxelmap returns, then check blocktypes has that…

how would i test witch is not valid?

here just incase heres my full script

using UnityEngine;

public class Chunk
{

    public ChunkCoord coord;

    GameObject chunkObject;
    MeshRenderer meshRenderer;
    MeshFilter meshFilter;

    int vertexIndex = 0;
    List<Vector3> vertices = new List<Vector3>();
    List<int> triangles = new List<int>();
    List<Vector2> uvs = new List<Vector2>();

    byte[,,] voxelMap = new byte[VoxelData.ChunkWidth, VoxelData.ChunkHeight, VoxelData.ChunkWidth];

    World world;

    public Chunk(ChunkCoord _coord, World _world)
    {

        coord = _coord;
        world = _world;
        chunkObject = new GameObject();
        meshFilter = chunkObject.AddComponent<MeshFilter>();
        meshRenderer = chunkObject.AddComponent<MeshRenderer>();

        meshRenderer.material = world.material;
        chunkObject.transform.SetParent(world.transform);
        chunkObject.transform.position = new Vector3(coord.x * VoxelData.ChunkWidth, 0f, coord.z * VoxelData.ChunkWidth);
        chunkObject.name = "Chunk " + coord.x + ", " + coord.z;


        PopulateVoxelMap();
        CreateMeshData();
        CreateMesh();

    }

    void PopulateVoxelMap()
    {

        for (int y = 0; y < VoxelData.ChunkHeight; y++)
        {
            for (int x = 0; x < VoxelData.ChunkWidth; x++)
            {
                for (int z = 0; z < VoxelData.ChunkWidth; z++)
                {

                    voxelMap[x, y, z] = world.GetVoxel(new Vector3(x, y, z) + position);

                }
            }
        }

    }

    void CreateMeshData()
    {

        for (int y = 0; y < VoxelData.ChunkHeight; y++)
        {
            for (int x = 0; x < VoxelData.ChunkWidth; x++)
            {
                for (int z = 0; z < VoxelData.ChunkWidth; z++)
                {

                    if (world.blocktypes[voxelMap[x, y, z]].isSolid)
                        AddVoxelDataToChunk(new Vector3(x, y, z));

                }
            }
        }

    }

    public bool isActive
    {

        get { return chunkObject.activeSelf; }
        set { chunkObject.SetActive(value); }

    }

    public Vector3 position
    {

        get { return chunkObject.transform.position; }

    }

    bool IsVoxelInChunk(int x, int y, int z)
    {

        if (x < 0 || x > VoxelData.ChunkWidth - 1 || y < 0 || y > VoxelData.ChunkHeight - 1 || z < 0 || z > VoxelData.ChunkWidth - 1)
            return false;
        else
            return true;

    }

    bool CheckVoxel(Vector3 pos)
    {

        int x = Mathf.FloorToInt(pos.x);
        int y = Mathf.FloorToInt(pos.y);
        int z = Mathf.FloorToInt(pos.z);

        if (!IsVoxelInChunk(x, y, z))
            return world.blocktypes[world.GetVoxel(pos + position)].isSolid;

        return world.blocktypes[voxelMap[x, y, z]].isSolid;

    }

    void AddVoxelDataToChunk(Vector3 pos)
    {

        for (int p = 0; p < 6; p++)
        {

            if (!CheckVoxel(pos + VoxelData.faceChecks[p]))
            {

                byte blockID = voxelMap[(int)pos.x, (int)pos.y, (int)pos.z];

                vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 0]]);
                vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 1]]);
                vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 2]]);
                vertices.Add(pos + VoxelData.voxelVerts[VoxelData.voxelTris[p, 3]]);

                AddTexture(world.blocktypes[blockID].GetTextureID(p));

                triangles.Add(vertexIndex);
                triangles.Add(vertexIndex + 1);
                triangles.Add(vertexIndex + 2);
                triangles.Add(vertexIndex + 2);
                triangles.Add(vertexIndex + 1);
                triangles.Add(vertexIndex + 3);
                vertexIndex += 4;

            }
        }

    }

    void CreateMesh()
    {

        Mesh mesh = new Mesh();
        mesh.vertices = vertices.ToArray();
        mesh.triangles = triangles.ToArray();
        mesh.uv = uvs.ToArray();

        mesh.RecalculateNormals();

        meshFilter.mesh = mesh;
        //e
    }

    void AddTexture(int textureID)
    {

        float y = textureID / VoxelData.TextureAtlasSizeInBlocks;
        float x = textureID - (y * VoxelData.TextureAtlasSizeInBlocks);

        x *= VoxelData.NormalizedBlockTextureSize;
        y *= VoxelData.NormalizedBlockTextureSize;

        y = 1f - y - VoxelData.NormalizedBlockTextureSize;

        uvs.Add(new Vector2(x, y));
        uvs.Add(new Vector2(x, y + VoxelData.NormalizedBlockTextureSize));
        uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y));
        uvs.Add(new Vector2(x + VoxelData.NormalizedBlockTextureSize, y + VoxelData.NormalizedBlockTextureSize));


    }

}

public class ChunkCoord
{

    public int x;
    public int z;

    public ChunkCoord(int _x, int _z)
    {

        x = _x;
        z = _z;

    }

    public bool Equals(ChunkCoord other)
    {

        if (other == null)
            return false;
        else if (other.x == x && other.z == z)
            return true;
        else
            return false;

    }

}

(sigh)

Well I did explain how

i see but im also dumb asf

like how do i track the x y and z values ?

The beauty of C# is its a standard language with ample documentation and existing information: IndexOutOfRangeException Class (System) | Microsoft Learn

Print them to the console with Debug.Log, or use manage code debugging: Unity - Manual: Debug C# code in Unity

1 Like

i did the log thing but i also saw that the error expanded
“IndexOutOfRangeException: Index was outside the bounds of the array.
Chunk.CheckVoxel (UnityEngine.Vector3 pos) (at Assets/scripts/Chunk.cs:116)
Chunk.AddVoxelDataToChunk (UnityEngine.Vector3 pos) (at Assets/scripts/Chunk.cs:126)
Chunk.CreateMeshData () (at Assets/scripts/Chunk.cs:72)
Chunk…ctor (ChunkCoord _coord, World _world) (at Assets/scripts/Chunk.cs:38)
World.CreateNewChunk (System.Int32 x, System.Int32 z) (at Assets/scripts/World.cs:155)
World.CheckViewDistance () (at Assets/scripts/World.cs:81)
World.Update () (at Assets/scripts/World.cs:39)”
I’m still new to game dev

i did a debug log for xyz but idk how to track the stuff for (blocktypes) its in this script

using System.Collections.Generic;
using UnityEngine;

public class World : MonoBehaviour {

    public int seed;
    public BiomeAttributes biome;
    public float test;

    public Transform player;
    public Vector3 spawnPosition;

    public Material material;
    public blockType[] blocktypes;

    Chunk[,] chunks = new Chunk[VoxelData.WorldSizeInChunks, VoxelData.WorldSizeInChunks];

    List<ChunkCoord> activeChunks = new List<ChunkCoord>();
    ChunkCoord playerChunkCoord;
    ChunkCoord playerLastChunkCoord;

    private void Start() {

        Random.InitState(seed);

        spawnPosition = new Vector3((VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f, VoxelData.ChunkHeight + 2f, (VoxelData.WorldSizeInChunks * VoxelData.ChunkWidth) / 2f);
        GenerateWorld();
        playerLastChunkCoord = GetChunkCoordFromVector3(player.position);
        

    }

    public void Update() {

        playerChunkCoord = GetChunkCoordFromVector3(player.position);
      
        // Only update the chunks if the player has moved from the chunk they were previously on.
        if (!playerChunkCoord.Equals(playerLastChunkCoord))
            CheckViewDistance();
       

    }

    void GenerateWorld () {

        for (int x = (VoxelData.WorldSizeInChunks / 2) - VoxelData.ViewDistanceInChunks; x < (VoxelData.WorldSizeInChunks / 2) + VoxelData.ViewDistanceInChunks; x++) {
            for (int z = (VoxelData.WorldSizeInChunks / 2) - VoxelData.ViewDistanceInChunks; z < (VoxelData.WorldSizeInChunks / 2) + VoxelData.ViewDistanceInChunks; z++) {

                CreateNewChunk(x, z);

            }
        }

        player.position = spawnPosition;

    }

    ChunkCoord GetChunkCoordFromVector3 (Vector3 pos) {

        int x = Mathf.FloorToInt(pos.x / VoxelData.ChunkWidth);
        int z = Mathf.FloorToInt(pos.z / VoxelData.ChunkWidth);
        return new ChunkCoord(x, z);

    }
    
    void CheckViewDistance () {

        ChunkCoord coord = GetChunkCoordFromVector3(player.position);

        List<ChunkCoord> previouslyActiveChunks = new List<ChunkCoord>(activeChunks);

        // Loop through all chunks currently within view distance of the player.
        for (int x = coord.x - VoxelData.ViewDistanceInChunks; x < coord.x + VoxelData.ViewDistanceInChunks; x++) {
            for (int z = coord.z - VoxelData.ViewDistanceInChunks; z < coord.z + VoxelData.ViewDistanceInChunks; z++) {

                // If the current chunk is in the world...
                if (IsChunkInWorld (new ChunkCoord (x, z))) {

                    // Check if it active, if not, activate it.
                    if (chunks[x, z] == null)
                        CreateNewChunk(x, z);
                    else if (!chunks[x, z].isActive) {
                        chunks[x, z].isActive = true;
                        activeChunks.Add(new ChunkCoord(x, z));
                    }

                }

                // Check through previously active chunks to see if this chunk is there. If it is, remove it from the list.
                for (int i = 0; i < previouslyActiveChunks.Count; i++) {

                    if (previouslyActiveChunks[i].Equals(new ChunkCoord(x, z)))
                        previouslyActiveChunks.RemoveAt(i);
                       
                }

            }
        }

        // Any chunks left in the previousActiveChunks list are no longer in the player's view distance, so loop through and disable them.
        foreach (ChunkCoord c in previouslyActiveChunks)
            chunks[c.x, c.z].isActive = false;

    }

    public byte GetVoxel (Vector3 pos) {

        int yPos = Mathf.FloorToInt(pos.y);

        /* IMMUTABLE PASS */

        // If outside world, return air.
        if (!IsVoxelInWorld(pos))
            return 0;

        // If bottom block of chunk, return bedrock.
        if (yPos == 0)
            return 1;

        /* BASIC TERRAIN PASS */

        int terrainHeight = Mathf.FloorToInt(biome.terrainHeight * Noise.Get2DPerlin(new Vector2(pos.x, pos.z), 0, biome.terrainScale)) + biome.solidGroundHeight;
        byte voxelValue = 0;

        if (yPos == terrainHeight)
            voxelValue = 3;
        else if (yPos < terrainHeight && yPos > terrainHeight - 4)
            voxelValue = 5;
        else if (yPos > terrainHeight)
            return 0;
        else
            voxelValue = 2;

        /* SECOND PASS */

        if (voxelValue == 2) {

            foreach (Lode lode in biome.lodes) {

                if (yPos > lode.minHeight && yPos < lode.maxHeight)
                    if (Noise.Get3DPerlin(pos, lode.noiseOffset, lode.scale, lode.threshold))
                        voxelValue = lode.blockID;

            }

        }

        return voxelValue;


    }

    void CreateNewChunk (int x, int z) {

        chunks[x, z] = new Chunk(new ChunkCoord(x, z), this);
        activeChunks.Add(new ChunkCoord(x, z));

    }

    bool IsChunkInWorld (ChunkCoord coord) {

        if (coord.x > 0 && coord.x < VoxelData.WorldSizeInChunks - 1 && coord.z > 0 && coord.z < VoxelData.WorldSizeInChunks - 1)
            return true;
        else
            return
                false;

    }

    bool IsVoxelInWorld (Vector3 pos) {

        if (pos.x >= 0 && pos.x < VoxelData.WorldSizeInVoxels && pos.y >= 0 && pos.y < VoxelData.ChunkHeight && pos.z >= 0 && pos.z < VoxelData.WorldSizeInVoxels)
            return true;
        else
            return false;

    }

}

[System.Serializable]
public class blockType {

    public string blockName;
    public bool isSolid;

    [Header("Texture Values")]
    public int backFaceTexture;
    public int frontFaceTexture;
    public int topFaceTexture;
    public int bottomFaceTexture;
    public int leftFaceTexture;
    public int rightFaceTexture;

    // Back, Front, Top, Bottom, Left, Right

    public int GetTextureID (int faceIndex) {

        switch (faceIndex) {

            case 0:
                return backFaceTexture;
            case 1:
                return frontFaceTexture;
            case 2:
                return topFaceTexture;
            case 3:
                return bottomFaceTexture;
            case 4:
                return leftFaceTexture;
            case 5:
                return rightFaceTexture;
            default:
                Debug.Log("Error in GetTextureID; invalid face index");
                return 0;


        }

    }

}

its a script its self ig

That is not debugging.

Here are some notes on IndexOutOfRangeException and ArgumentOutOfRangeException:

http://plbm.com/?p=236

Steps to success:

  • find which collection it is and what line of code accesses it <— (critical first step!)
  • find out why it has fewer items than you expect
  • fix whatever logic is making the indexing value exceed the collection size

Remember also:

  • a collection with ZERO elements cannot be indexed at all: it is empty
  • you might have more than one instance of this script in your scene/prefab
  • the collection may be used in more than one location in the code
  • indices start at ZERO (0) and go to the count / length minus 1.

This means with three (3) elements in your collection, they are numbered 0, 1, and 2 only.

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

1 Like

Just to break it down how it’s done ^^

You have this line which will throw an index out of bounds exception.

return world.blocktypes[voxelMap[x, y, z]].isSolid;

Those errors are thrown by arrays or colliections whenever you pass in an index that is either too large or too small. You have two array accesses in the same line. So first step is, break it up

byte blockIndex = voxelMap[x, y, z];
blockType block = world.blocktypes[blockIndex];
return block.isSolid;

This is just breaking it up into individual lines. The advantage is that if an error occurs now, you can tell by which part. We haven’t done any error checking yet. This is the same line of code, just separated into individual lines. Now we can do some simple checks or print out the values.

Debug.Log($"Getting block from voxelMap[{x}, {y}, {z}]");
byte blockIndex = voxelMap[x, y, z];
Debug.Log($"Got block index {blockIndex}");
Debug.Log($"Size of blocktypes: {world.blocktypes.Length}");
blockType block = world.blocktypes[blockIndex];
if (block == null)
    Debug.LogError($"Block with index {blockIndex} seems to be null in the blocktypes array");
return block.isSolid;

When running with this code you should get a ton of information to figure out where the issue is.

My guess may be that your FloorToInt may result in a negative value since you use Vector3 which are float values, when you floor them and they are ever so slightly below 0, it would floor to -1. But lets see what you get.

Depending on what your source coordinates actually are, using RoundToInt probably makes more sense in many cases. Especially when the coordinates are actually on the grid lines. With floor it will be luck if you hit one or the other values.

1 Like

voxle map goes to 15. 57. 14 then goes to 0,57,0 then x and z slowly goes back to 15 and 14 going by +1
block index comes out to 5 (slowly goes from 1-5) +1
block types are also 5

If I understood this correctly, you have only 5 blocktypes? If that’s the case, indices 1 to 5 would be wrong. If you have 5 block types, the indices are 0 to 4 (0, 1, 2, 3, 4). Keep in mind that “air” / nothing needs a type as well and it’s usually the first one, “0”. So check your logic again.

Whe. I ment 1-5 i ment it slowly went 1 to 5
Going +1 every few frames
On phone im using a dif acc sorry

so how big (you should know) is blocktypes as Bunny says if it s 5 big, its 0-4 not 1-5, so like Bunny and I have said you need to show each value and it will tell you whats wrong


(im still new to this im not fully understanding ) ive givin all info i am able to
block types is 5
and no blocks are coming up as null

right but if you have blocktype[5] it will be an invalid reference

1 Like

omg bro im so happy u helped me with this
sorry u had to deal with my dumbness

1 Like