MINECRAFT CLONE
Aug 27, 2025 - Solo Project - Unity C#
Aug 27, 2025 - Solo Project - Unity C#
The world is split into 16x16x16 block chunks
To see the world, all nearby chunks need meshes
To make a mesh, loop through all the blocks in a chunk and check for an air block in all directions of that block
If a block is adjacent to air, insert a face ( don't forget UVs )
To prevent lag spikes, implement a throttle feature that spreads the mesh generation work over multiple frames
To prevent memory leaks, deallocate chunks that are out of range ( chunks are stored on the heap )
Use multithreading to speed up the work of generating the chunk data, not the mesh
Leverage central game loop to implement simple physics
Convert player position into block position, use that to check for solid blocks under, above, in front, etc of the player for collision
If the player is inside a water block, different movement rules apply
The same isSolid() method that is used for mesh generation is also used for player collision
☆ This is the code that is responsible for generating solid meshes.
The function writes to std::vectors of the vertices and the triangles of the mesh.
The Atlas is used to set the UVs of each block's face. The texture atlas has no functionality, it just holds data for which blocks have what UVs.
<--
// LEFT. ===
if (!isSolid(blockPos + left, false, chunkSize, chunks)) {
verts.emplace_back(blockPos + glm::ivec3{ low, low, high }, left);
verts.emplace_back(blockPos + glm::ivec3{ low, high, high }, left);
verts.emplace_back(blockPos + glm::ivec3{ low, high, low }, left);
verts.emplace_back(blockPos + glm::ivec3{ low, low, low }, left);
setCurrentFaceUVs(verts, atlas.maps.at(blockType).faces[Direction::LEFT]);
faceCount++;
}
☆ This snippet add the left faces of blocks to the overall chunk mesh, for solid blocks only.
<--
☆ Here we see how the player collides with the world. Notice how it uses the same isSolid() function.
The main challenge here was making the player vertically be 2 blocks high. The eyes / camera of the player needs to also be 1.5 blocks of the ground.
☆ This is a snippet from main.cpp.
This is the central game loop. Here we see how the game is updated first. Then, the shadows are processed. After, the game as a whole is drawn.
Finally, the transparent world elements and UI are drawn.
<--
My school semester is split up into four parts. For this part I also wanted to make a Minecraft-inspired level editor so this C++ project was perfect. I spent around 30% of my time setting up a game-engine like environment for myself.
As with most school projects, a good starting point was finding plenty of reference material. The most crucial of these are compiled at the end of this page.
My main hassle with this project was figuring out the link between my own coordinate system and the one used in my shaders. For example: for objects that can rotate, not only do the vertices need to rotate, the normals need to rotate too. This is untrue for chunks as they cannot rotate ( and since many chunks are loaded at a time, this optimization is essential ).