1
\$\begingroup\$

I'm working my way through this voxel tutorial in Unity. I'm on part 3, and it's showing me how to create a chunk within the world.

I've copied the code, but I think I am missing something. The error that shows up is:

NullReferenceException: Object reference not set to an instance of an object Chunk.UpdateChunk () (at Assets/scripts/Chunk.cs:76) Chunk.Update () (at Assets/scripts/Chunk.cs:34)

The offending code is at this line:

meshData = blocks[x, y, z].Blockdata(this, x, y, z, meshData);

Chunk.cs

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
[RequireComponent(typeof(MeshCollider))]

public class Chunk : MonoBehaviour
{

    private Block[,,] blocks = new Block[chunkSize, chunkSize, chunkSize];

    public static int chunkSize = 16;
    public bool update = true;

    MeshFilter filter;
    MeshCollider coll;

    public World world;
    public WorldPos pos;

    void Start()
    {
        filter = gameObject.GetComponent<MeshFilter>();
        coll = gameObject.GetComponent<MeshCollider>();
    }

    //Update is called once per frame
    void Update()
    {
        if (update)
        {
            update = false;
            UpdateChunk();
        }
    }

    public Block GetBlock(int x, int y, int z)
    {
        if (InRange(x) && InRange(y) && InRange(z))
            return blocks[x, y, z];
        return world.GetBlock(pos.x + x, pos.y + y, pos.z + z);
    }

    public static bool InRange(int index)
    {
        if (index < 0 || index >= chunkSize)
            return false;

        return true;
    }

    public void SetBlock(int x, int y, int z, Block block)
    {
        if (InRange(x) && InRange(y) && InRange(z))
        {
            blocks[x, y, z] = block;
        }
        else
        {
            world.SetBlock(pos.x + x, pos.y + y, pos.z + z, block);
        }
    }

    // Updates the chunk based on its contents
    void UpdateChunk()
    {
        MeshData meshData = new MeshData();

        for (int x = 0; x < chunkSize; x++)
        {
            for (int y = 0; y < chunkSize; y++)
            {
                for (int z = 0; z < chunkSize; z++)
                {
                    // **NullReferenceException occurs on this line:**
                    meshData = blocks[x, y, z].Blockdata(this, x, y, z, meshData);
                }
            }
        }

        RenderMesh(meshData);
    }

    // Sends the calculated mesh information
    // to the mesh and collision components
    void RenderMesh(MeshData meshData)
    {
        filter.mesh.Clear();
        filter.mesh.vertices = meshData.vertices.ToArray();
        filter.mesh.triangles = meshData.triangles.ToArray();

        filter.mesh.uv = meshData.uv.ToArray();
        filter.mesh.RecalculateNormals();

        coll.sharedMesh = null;
        Mesh mesh = new Mesh();
        mesh.vertices = meshData.colVertices.ToArray();
        mesh.triangles = meshData.colTriangles.ToArray();
        mesh.RecalculateNormals();

        coll.sharedMesh = mesh;
    }

}

However, I think it's maybe not the code that's the problem. Rather, I am missing a step. There is a section of the tutorial that says:

Let's start with a function to create new chunks, since chunks are game objects we'll need to use the instantiate method with a prefab to create the chunks so create a variable chunkPrefab:

 public GameObject chunkPrefab;

And also create a prefab of a chunk. Use the chunk object we've been using or create a new one. It just needs to be a game object with the material applied and chunk script which automatically includes the mesh renderer, mesh filter and mesh collide . By the way make sure your mesh collider has convex set to false or your colliders wont work. Make a prefab of it by dragging it from the hierarchy to the project view. Then delete it from the scene and make a new object with the world script on it and set the chunkPrefab variable to the one we just made.

How do I create a prefab of a chunk? Do I go to:

Assets->Create->Prefab

and then assign my chunk.cs script to it? Or do I assign my current gameobject to it (which has chunk.cs and the tileset material attached)? Or am I misreading this entirely?

Here is what my scene looks like so far: enter image description here

Pictures would really help!

\$\endgroup\$
  • \$\begingroup\$ blocks[x, y, z] returns null. You have not included its definition in your post, so I am unable to diagnose further. See also stackoverflow.com/questions/4660142/… \$\endgroup\$ – Draco18s Feb 3 '16 at 19:22
  • \$\begingroup\$ @Draco18s I've added the entire Chunk.cs code. You can also download the entire project on the tutorial's webpage, which includes all the source code for part 3 (link is at bottom of page). \$\endgroup\$ – meepboop Feb 3 '16 at 19:27
  • 2
    \$\begingroup\$ Well, you never fill the array with anything. What did you expect it to contain? \$\endgroup\$ – Draco18s Feb 3 '16 at 19:30
  • \$\begingroup\$ @Draco18s In his tutorial he has a script called World.cs, and it generates the blocks at (x,y,z) in his Start() method. I think the code is valid, it's just for some reason I have not done some step in Unity that calls World.cs Start() method, so the blocks are all null. I'm not sure what step I'm missing, but I am guessing it has to do with the Prefab step I listed. I don't understand what that missing step is exactly though. \$\endgroup\$ – meepboop Feb 3 '16 at 19:42
  • \$\begingroup\$ Is your World script attached to a GameObject in the scene hierarchy? \$\endgroup\$ – Draco18s Feb 3 '16 at 19:43
1
\$\begingroup\$

Click your chunk gameobject and drag it down in your assets directory. You now have a prefab of your chunk object. Drag this prefab into the world script or where it is needed. Delete your chunk gameobject from the hierarchy. That should be it... good luck, this is a good tutorial.

\$\endgroup\$
0
\$\begingroup\$

You must make a chunk prefab, remove it from your scene hierarchy, and add a new game object to the scene with the World.cs script attached and with the chunk prefab as the value of the world script's variable.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.