Why You Can't Build Minecraft with Cubes

Penny de Byl
A free video tutorial from Penny de Byl
International Award Winning Professor & Best Selling Author
4.7 instructor rating • 19 courses • 75,182 students

Lecture description

It might seem like a good idea to build a world like Minecraft with cubes. But an examination of the performance of rendering such a world proves otherwise. This lecture takes a look at the issue.

Learn more from the full course

How to Program Voxel Worlds Like Minecraft with C# in Unity

A comprehensive guide to blocky mesh building for procedurally-generated worlds like those found in Minecraft.

06:19:56 of on-demand video • Updated November 2020

  • Build a cube-based geometric world like that generated in Minecraft.
  • Navigate and manipulate discrete values in 3d space.
  • Build and skin meshes from scratch using C#.
  • Save and Retrieve Serialised Data.
  • Build and manage a voxel data structure.
English [Auto] In this lecture we're going to build a very simple world created with coupes and we're going to use the code that was presented in the previous lecture where there was a nested follow up and it was instantiating cube prefabs on the screen at an x y and Zed location. So to follow along. Open up unity and what you'll need for this is a script called Camera Control which I've included with the resources for this lecture. Now this script you can add to your mind camera and what it will do is make your main camera behave in a similar manner to the one that you get in the scene. So in the scene we can use alt to orbit and we can use q to pan around this is the case and when we're running this the camera control script added to the camera will allow you to do the same things in the game window which is useful when you're trying to move around and look at things that you're building. So begin by creating a new project and bring in that script and apply it to the default main camera. So let's begin first of all in the hierarchy. I'm going to create an empty so right click and create empty. I don't want it attached to my camera and let's call it world and onto it. We're going to add some code called World controller. So in your project you'll go create a shop and we'll call control and then attach that file to your world. Then check in the hierarchy by clicking that it is in fact added in let's open that file up and we will add some code. The code will take in a prefab which will represent our block and we'll create that in a minute. So that's our first public at the top here. I've also got a public variable in integer which will be our world size and this will be used to set the with the depth and the height so it will all be the same dimensions. Next I've got an enumerator build world function added here. The reason I've got this as an enumerator is so that we can loop through it but also have a rest either after a single cube is built or after a row or whatever you want. If you don't put this in here you can just build the entire world by zipping through all of the loops in one go. But you won't see it being built. And the other problem is if you set this world size way too high then you will crash unity. And if you can see it being built step by step and you've got this numerator that is yielding and actually having a pause in its function then you can quit your world if it's getting way too big when you're trying to run it in the editor. So I will warn you now we're starting at two and you might want to rent this up to 200 straight away. Do not do it as you're about to see. It's really not a good idea. Koso inside outbuild world method here. You can see three full clips that we've already investigated so I've got the Zad on the ALSA. I've got the Y. And then I've got the X on the inside. And what these are doing it looping through all the different coordinate values in your 3D world between 0 and world size in each dimension. Now each time it comes around it's going to build a new vector which will be the position of the particular cube its about to make. So we just putting an X Y Zed. The reason we can get away with putting a single cube at x y is it time and not have them overlap is that H cube h default unity cube is 1 in size. So we're working with whole numbers and we're working with keep sizes that are exactly 1. It makes the math in this world so much easier to work like that. So the cube is instantiated from a block and it's set to the position that we've calculated up here. And at a zero rotation because the rotation is. Case doesn't really matter. Next I'm also giving the cube its been created a name based on its X Y and Zed values so that you can see where it is. And I guess you can see it in the transform as well but it also helps to identify and find it later on. Now off to the x I've got the yield if you want to yield after each single cube you would move this yield up into here. Inside the X loop the issue I had there was just way too slow so this will build sort of one row at a time and then keep yielding for you so you can see that going on. Now just down below that which is doing all of the work for us I've got a start function which will start the car retain for build world and there's nothing inside of the update. All right so let's save that and switch back to unity. Now what you want to do if you select the world object in the hierarchy is it needs to have a block and the block is our prefabs cube. So in the hierarchy right click and create a 3D object cube. There it is now. It will automatically be one by one by one in size which is exactly what we want with that cube. Drag and drop it into the project and that will create a pre-fab out of it in the hierarchy. Let's just remove it. We don't need it anymore. And select the world again. And you want to drag and drop the cube pre-fab onto the exposed block variable there. And now this cube will be used to build our world. So let's press play and have a look what happens. OK. So that happened quite fast because there's only a world which is two by two by two. And if you go to the same view you'll be able to select each individual cube so you can see that key. If I move out is at zero in the x 1 in the Y and 0 in the Zed's so the names have been added here. You'll see something called a fake cam target that's being used by the script that we added to our camera so we could move it around in the game view. So you'll find if you're in games you can use the K to orbit and the cue to move around so it's very handy for seeing what we're building. And for each project we create from now on you should just bring that in anyway until we start creating first person controls and those sorts of things. All right. So that's your key. Now if we just stop running this and go back to World and let's put in five. In this case for the world size and press play you get a much bigger cube made of many little cube so it's now five by five by five. And now let's go back to our world and ramp it up to let's say 30 cubes and press play now this is where that yield comes in handy because it allows us to still have control over our game environment without freezing the whole thing while it's trying to finish building all of those cubes. And you can see it being constructed row by row by row. In this case now imagine you want to build a world the size of Minecraft. This is going to be a quite a slow process isn't it. And the idea of building a world like Minecraft. Just from cubes sounds like a good idea because cubes are just so convenient. But when it comes to rendering it out it's a really bad idea. So the more cues you get the more lag that you will get in the environment and as I said previously there aren't any cubes in Minecraft which is the genius of it. So we're going to now investigate what's going on with all of these cues and have a look at how adding more and more Keeves on affects the performance of your game. So let's stop playing Go back and change your world size to only working with two by two by two lots of cubes in the world then we'll press play again and this time in the game window we're going to open up the stats area. So there's a little button at the top called stats and if you open that up you can see some of the performance factors of the game you're running now. Of particular interest to us in developing this voxel world is to look at the Frayne's first second and the number of batches. The second is how many updates to the screen you're getting per second. Now if this falls down below 20 you'll start to get jittery ness and lagging in your game world. So the human eye is capable of detecting smooth movement in anything above 15 frames per second and regular film is shot at 24 frames per second which makes it really quite smooth in a fast action. Things like games you need much higher frames per second to fit in all of the action and to create smooth movement. So I'm currently running at 80 frames per second which is really good on my machine yours might show a different value here. And considering we've only got IQ sitting in an environment you wouldn't think this is going to drop very low for that. Now the batches tells you how many things need to be processed before you get an image on the screen. And this is running everything through the C-p you and the GP. So unity here is putting everything that needs to be drawn on the screen which is your geometry and any chaises materials textures that sort of thing. Lauching as well. It's batching them together into seven batches and they Forte's looping through seven times and then bam you get an image on the screen. Then I'll do another seven processes and you'll get another image on the screen and it's telling us that it's also saved 28 batches or 28. Lots of things but putting them into these 7 batches contained in those seven batches 400 triangles which make up all of these cubes and 800 vertices. And we will look at the geometry of cubes in a little while. But for now of course the more cubes you've got the more triangles and vertices that you're going to have. So this is at 800 frames per second seven batches for a world that is two by two by two. Now we're lucky to do as a little bit of an experiment for yourself is to run this with a world size of two and write down the frames per second and then stop running. And let's change it to four. And press play. And then once it's finished drawing right down again the frames per second and cave incrementing and doubling this so then go to it and run it and right down the corresponding frames per second. And what we're going to do is to graph them. So here's my graph. All frames per second. This is the world size and you can say that it went along I.K. holding at about 80 frames per second until it got to a world that was around 12 by 12 by 12 from that performance dropped dramatically and around 32 to 32 by 32 in world saw as I was getting 3 frames per second. Now currently every cube that we are generating is sharing the same material. So unity is doing its best to batch up our geometry and anything that has the same material and it can be matched together. But when materials are different it combat them and the performance goes down even more. So lets have a look at that. Go into a world script thats open that up and in here each time we instantiate a new cube we're going to just add in this line. What this will do is grab hold of the current material that's on the cube and set it to a new material. And this case we're just making it a standard Shida but it will still be a different shader on every single cube that's generated. So now save that and go back into unity and run the experiment again by changing the world size. What you can say from my own experiment is that the cubes with their own individual materials shown in red here the performance drops off much more dramatically than it did before when they all used the same material. But we still get a rapid decline in the performance. What this tells us is when we go about our business of creating a very blocky world we need to take into consideration the number of materials and the number of meshes that are in it and therefore right from the outset we need to go back and consider these things by completely reinventing the cube.