- Home /
[Tutorial] Minecraft Chunks
After noticing the vast amount of help for Minecraft clones I've decided to post up a few tutorials explaining different aspects of building one. In this section I'll try my best to show you how to create "Chunks" although I'll apologise for my explanations now as I'm awful at explaining.
I would also like to credit the MinePackage located HERE as most of the code has been taken and rewritten out from this. If you'd like to learn more there is another thread which you can check out HERE
If people like this then I'll make a few more, if any of my information is incorrect then I apologise, let me know and I'll update it, or if you have a better explanation or extra info just add it as an answer.
So what is a "Chunk" then?
In Minecraft think of the thousands of blocks there are to your disposal, now what would happen if we were to render them all every frame? Well our FPS would be non existant. So one way we can help speed things up is to slice our level in to manageable "Chunks".
How would this speed up the game?
Instead of rendering the entire level over and over, we could just take the chunks within a certain radius of our player and only render those, not only does this speed things up but it also means we aren't working with the entire level only a small portion of it. This is bordering another aspect but what if we wanted to find out what blocks the player is able to see? Rather than doing this for the entire level every frame we can just check the surrounding chunks.
What will I learn for this then?
Fingers crossed you will be able to create empty chunks in your world to a size you choose. This is merely showing you how chunks work and how to create them, they have no functionality. I'm posting this because it took me a while to scan examples to learn how they work.
Now I know chunks, what next?
Well I'm still learning myself but I would recommend looking up Octrees, Procedural Meshes, Texture atlas' and Perlin Noise (Hopefully if I get time I'll post up some stuff about these)
WorldGameObject.cs attaches to an empty GameObject
WorldGameObject.cs
using UnityEngine;
using System.Collections;
public class WorldGameObject : MonoBehaviour {
private WorldData world = new WorldData(); // Holds all the data about our world
public Transform chunkPrefab; // A template of a chunk
public Transform[,,] chunkGO; // A list of our chunks coords
void Start () {
// So we start by initializing a grid for our chunks
// In our world data script we run a function that
// Creates a 3 dimensional array and sets the coords
// For each Chunk
world.InitChunkGrid();
// After initializing our grid for our chunks
// We can now go ahead and instantiat our chunks
// Referencing their Transform
CreateChunks();
}
private void CreateChunks()
{
// This will only contain the locations of our chunks
// The actually chunk data gets stored in our ChunkData script
chunkGO = new Transform[world.ChunksX,world.ChunksY,world.ChunksZ];
// 3 for loops, x,y,z each increment will represent a chunk
// We only want to go as high as the amount of chunks in our
// World so we set the loop amount as ChunksX,ChunksY,ChunksZ
for (int x = 0; x < world.ChunksX; x++)
{
for (int y = 0; y < world.ChunksY; y++)
{
for (int z = 0; z < world.ChunksZ; z++)
{
// We get the chunk from the array located at x,y,z
// And store it as the current chunk we're working on
ChunkData curChunk = world.chunks[x, y, z];
// Here we create a Vector3 of where the chunk will be placed
// the x position on our vector3 is the current chunk's x coord multiplied
// By the chunk width for example if curChunk is 2 we multiply it by our ChunkWidth,
// Which in this case would be 32 because our chunks are 32x32x128 meaning
// the chunks x position would be 64, we don't need to worry about Y because
// Our chunk height is 1, then we do the same on the Z axis
Vector3 chunkInstPos = new Vector3(curChunk.X * world.ChunkWidth, 0, curChunk.Y * world.ChunkHeight);
// Now that we have where to we want put our chunk lets create a chunk instance
Transform chunkInst = Instantiate(chunkPrefab, chunkInstPos, Quaternion.identity) as Transform;
// After creating an instance of a chunk lets set the parent to our World GameObject
chunkInst.parent = transform;
// Lets rename the chunk to something more managable
// In our ChunkData script is a function called ToString
// This basically returns a string of the chunks position
// It will return something like Chunk ( 1,0,1 )
chunkInst.name = curChunk.ToString();
// Now our chunk exists lets make a reference of it's
// Position by adding it to our array
chunkGO[x, y, z] = chunkInst;
}
}
}
}
}
WorldData.cs doesn't need to be attached to anything
WorldData.cs
using System.Collections;
public class WorldData {
private int chunkWidth = 32, chunkHeight = 128, chunkDepth = 32; // The dimensions of each chunk in blocks, so each chunk is 32 blocks in width and depth but 128 blocks in height
private int chunksX = 8, chunksY = 1, chunksZ = 8; // How many chunks we want to generate in the world along each axis
public ChunkData[,,] chunks; // And array of our chunks so we can keep track of them
public const int BottomChunkBorderRow = 0, LeftChunkBorderColumn = 0;
public void InitChunkGrid()
{
// Lets initialize our array where our chunk data will be stored
chunks = new ChunkData[chunksX,chunksY,chunksZ];
// Our for loops so we can iterate through and set our chunk
// Position in the array
for (int x = LeftChunkBorderColumn; x <= RightChunkBorderColumn; x++)
{
for (int y = BottomChunkBorderRow; y <= TopChunkBorderRow; y++)
{
for (int z = 0; z < chunksZ; z++)
{
// Create a new set of ChunkData at x,y,z
chunks[x, y, z] = new ChunkData(x, y, z);
}
}
}
}
// Chunk width,height,depth Functions just allow us
// To get and set the value of our vars because they're private
public int ChunkWidth
{
get { return chunkWidth; }
set { chunkWidth = value; }
}
public int ChunkHeight
{
get { return chunkHeight; }
set { chunkHeight = value; }
}
public int ChunkDepth
{
get { return chunkDepth; }
set { chunkDepth = value; }
}
// Chunks X,Y,Z Functions just allow us
// To get and set the value of our vars because they're private
public int ChunksX
{
get { return chunksX; }
set { chunksX = value; }
}
public int ChunksY
{
get { return chunksY; }
set { chunksY = value; }
}
public int ChunksZ
{
get { return chunksZ; }
set { chunksZ = value; }
}
public int TopChunkBorderRow
{
get { return chunksY - 1; }
}
public int RightChunkBorderColumn
{
get { return chunksX - 1; }
}
}
ChunkData.cs doesn't need to be attached to anything
ChunkData.cs
using System.Collections;
public class ChunkData {
private int x,y,z; // Create 3 ints called x,y,z to store our position in our WorldData array
// When ever our chunkData, we will send in
// The position it will be stored in the WorldData array
public ChunkData(int _x, int _y, int _z)
{
x = _x;
y = _y;
z = _z;
}
// X,Y,Z Functions just allow us to get and set the value
// Of our vars x,y,z because they're private
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public int Z
{
get { return z; }
}
// We will use this when renaming our chunk
// So it is something more readable and managable
// Instead of having them all name Chunk(clone)
public override string ToString()
{
return string.Format("Chunk ( {0},{1},{2} )", x,y,z);
}
}
Sir I do believe this is meant for the forums, not a questioning site, considering its a tutorial.
Can we mark this a community wiki entry?
Although, I doubt this will stop the endless questions about it- people find it easier to ask a new question than to use a search function.
To fit the QA format, why not just make it a question "How to do $$anonymous$$ecraft chunks?" and provide what you have above as an answer? You could even just give a rough overview and point to the forums for the full tutorial.
Nothing is keeping you from editing the question and then posting your answer :)
Answer by D1AM0ND4UN73R · Aug 22, 2012 at 09:25 AM
This is not a question. This site is only for questions, not tutorials.
Please don't post comments as answers. Post comments by clicking the [add new comment] button, a window then open for you to type in. Answer fields are for answers only, as this is a knowledge base.
Are you a retard? I made this post like 2 years ago, if you don't have a proper answer fuck off, this site is only for questions and answers.
CarlLawl you took the time to give back to this community and i don't see a single thank you, just moaning people!
Well THAN$$anonymous$$ YOU, very helpful.
Answer by drollestprawn4 · Dec 11, 2020 at 08:44 PM
This site is for people to post questions and then other people to answer them not to post an answer to a question that wasn't asked.
Answer by Vaughnderrick · May 30, 2017 at 07:41 AM
Copy This Code Here:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Block
{
public int type;
public bool vis;
public Block(int t, bool v)
{
type = t;
vis = v;
}
}
public class Woldcreator : MonoBehaviour
{
public static int width = 128;
public static int depth = 128;
public static int height = 128;
public int heightSacale = 20;
public float detailScale = 25.0f;
public GameObject BlockDirtStone01;
public GameObject BlockGrass01;
public GameObject Blocksnow01;
Block[,,] worldBlock = new Block[width, height, depth];
void Start()
{
int seed = (int) Network.time * 10;
for(int z = 0; z < depth; z++)
{
for (int x = 0; x < width; x++)
{
int y = (int) (Mathf.PerlinNoise((x+seed)/detailScale, (z+seed)/detailScale) * heightSacale);
Vector3 blockPos = new Vector3(x,y,z);
CreateBlock(y, blockPos, true);
while(y > 0)
{
y--;
blockPos = new Vector3(x, y, z);
CreateBlock(y, blockPos, false);
}
}
}
}
void CreateBlock(int y, Vector3 blockPos, bool create)
{
if (y > 15)
{
if(create)
Instantiate(Blocksnow01, blockPos, Quaternion.identity);
worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z] = new Block(1, create);
}
else if (y > 5)
{
if(create)
Instantiate(BlockGrass01, blockPos, Quaternion.identity);
worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z] = new Block(2, create);
}
else
{
if(create)
Instantiate(BlockDirtStone01, blockPos, Quaternion.identity);
worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z] = new Block(3, create);
}
}
void DrawBlock(Vector3 blockPos)
{
if (blockPos.x < 0 || blockPos.x >= width || blockPos.y < 0 || blockPos.y >= height || blockPos.z < 0 || blockPos.z >= depth)return;
if (!worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].vis)
{
worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].vis = true;
if (worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].type == 1)
Instantiate(Blocksnow01, blockPos, Quaternion.identity);
else if (worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].type == 2)
Instantiate(Blocksnow01, blockPos, Quaternion.identity);
else if (worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].type == 3)
Instantiate(Blocksnow01, blockPos, Quaternion.identity);
else
worldBlock[(int)blockPos.x, (int)blockPos.y, (int)blockPos.z].vis = false;
}
}
//ok
void Update()
{
if(Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width / 2.0f, Screen.height / 2.0f, 0));
// hinter hit gibt der wert die reich weite an z.b 4.0f wie weit der char Blöcke abbauen kann von seinen stand punkt aus
if (Physics.Raycast(ray, out hit, 4.0f))
{
Destroy(hit.transform.gameObject);
}
else if (Input.GetMouseButtonDown(1)) {
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay (new Vector3 (Screen.width / 2f, Screen.height / 2f, 0));
if (Physics.Raycast (ray, out hit, 50f)) {
Vector3 newBlockPos = hit.transform.position;
newBlockPos += hit.normal;
CreateBlock ((int)newBlockPos.y, newBlockPos, true);
}
}
}
}
It Will Create Small Minecraft Chuncks
Block Adds -Snow -Grass -Sand
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Object doen't move even though i did according lesson 1 Answer
Roll a Ball tutorial error 4 Answers
Tag: Siren is not defined? (Stealth Tutorial) 2 Answers
I am new and need help 1 Answer