Make Minecraft in Unity 3D Tutorial - 01 - The First Voxel

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome to my first attempt at making a code in tutorial video just to be original I'm doing a coding tutorial video on minecraft now I am by no means an expert I pretty much learn everything I've learned from these kinds of videos that I'm hoping to make here I'm not going to claim that my code is any more elegant or more efficient or better in any way than any of the more talented people out there while I'm hoping to do is make the code in such a way that is as easy as possible to follow along if you don't quite understand what's going on to begin with because that that part I do understand because that was me and still is me in a lot of cases but in this particular subjective I think I've managed to get to a point where I can at least help some people so I'm not gonna waste any time explaining what minecraft is if you hear I'm assuming you know what minecraft is so you may be wondering why it's such a big deal to make something like minecraft you could just use the built-in unity primitive thing there we have a cube we could quite easily duplicate that cube move it side move it next it would help if the first cubes in zero position move them next to each other and then programmatically put them all over the place and we've got lots of cubes now the reason for that is there's two reasons one it is very expensive because in terms of resources because each of these cube isn't its own game object which corazon collide areas Khorasan cube mesh you know so mesh renderers corazon transform it's very expensive to put all these objects on screen and then the other problem is that you need us have an actual limitation it can only draw so many game objects I can only have so many game objects in existence at once it's a high number it can get quite a lot of game objects on the screen but you're gonna hit that in a game like Minecraft because there are a lot of cubes so we're not going to do that the easier way is to actually draw what we call chunks I imagine most people who know Minecraft leaders know what chunks are and instead of drawing each individual cube you just draw the actual mesh of the outside of chunk so if you have ten cubes all along in a flat surface like a floor you don't need to draw anything under that floor because you can't see it until you start digging we'll get to that part so I've made a little reference till just help us understand this is a voxel or the Minecraft voxel and as you can see we have eight corners these are eight corners of the cube this is essentially the only location data that we need is to know where these four eight corners are so what we're going to do I've got back into unity and we'll make ourselves a nice little scripts folder because we want to keep everything nice and neat almost spell scripts right because that's always a good start and what we're going to do is we're going to make a lookup table that stores all of this information while it where these eight where these eight vertices are you can do this programmatically you can do it in four loops you can use math to work out where everything needs to be I'm not saying this is in any way more efficient it might actually be more efficient I'm not sure it's definitely not more elegant but like I said I'm trying to do this in a way that's easier to follow rather than any particular spectacular way of doing it so the way we're going to do this is we're going to create a self a static class we'll call this fox all data I'll open up this and we want it to be a static class because the whole point of this if it ever actually opens the whole point of this class is that it's just going to start data that we need it's not going to do anything else so it's it's not going to be attached to anything it's not gonna be edited it's just gonna star data so we get rid of mana behavior because we're not putting on anything public obviously static so we can access it from anywhere and then inside we're going to make a static array so this wants to be public static we're gonna make it read only because we don't want to get in edit is halfway through the game because that will cause all sorts of problems if the cube start changing size and things in the middle of a game when the because in theory minecraft the world is constantly being generated unless you have a set you generate everything at once the worldís constant will be generated so if you start changing the fundamental values of a voxel or a chunk or anything partway through the game you're gonna get all kinds of weird stuff happening so we're gonna call this voxel verts really matter what you call it as Fosbury so it helps to call it something that makes a bit of sense now we know just go back here we know how many verts there are each one of these red dots red spheres represents a verts so we know that there are eight verts there's always gonna be a verts on a cube now as we get later on and we start drawing things like stairs for example that's gonna change but we'll worry about that layer for now we know that all of our blocks have got a vert so we don't need to worry about what the size is because we can set it and so we're going to set it to 8 because papers that's where it is and then inside of here we're going to put 8 vector threes and these represent the locations of those verts so our first vector 3 is 0 0 0 luckily I've I need a little feature to this so I can show this so we'll go back to the front or the back not quite sure which way to orient it so we have 0 0 0 here and then 0 next to it next to the actual coordinate is the index there it's going to be in this array so here this is the first one in the index in the array so that is index 0 as you can see 1 0 0 is got index 1 so that's going to be the next one in the array and then 3 0 1 0 2 1 1 0 this order that you put these in isn't necessarily important it's not important that you do it the same way that I've done it but it is important for later on be orderman 0 0 1 and then finally 0 1 1 so there we have all of our vertices in an array for all of these coordinates so each one of these represents one of these now the way unity or any 3d thing draws a 3d object is by triangles so each one of these vertices three of them together can make up a triangle so if I click this one this one and this one we see we get a triangle between these this is how it's all polygonal 3d meshes are made it's just a collection of these triangles and obviously the more of these red dots you have the more detail you can have we're just drawing a block so we don't really need to worry about that sort of thing but obviously to draw the block we have this to draw a face of a block for it sorry we would have this triangle and then we would have this triangle and together that would make the face of a blocks and I've only coded this so that control wouldn't throwing a lot of time so I can't show you the whole face but you get the idea now the important thing about this is that the direction that the triangle is drawn in so right now I'm going 1 2 3 is very important because clockwise means forward or if you do it clockwise the way your face is as you're looking at it that's where it will draw the face if I spin round to the back here you'll see it disappears because the backside of a triangle is not rendered you would have to do some some fancy stuff to make it render both sides of a triangle so if I were to draw that triangle backwards we can't see it but if I spin round here there it is so all the triangles you have to add them in a clockwise order to the direction that you want them to actually face so if I go up here and I do it backwards you can't see anything but if I go the same three dots that way we get a triangle so the way that unity knows which triangles to add is we have we have two arrays we have vertices array which just stores these values here stores the location data of the vertices and then it has a triangle array and the triangle array is just an int array and what the inter a does is it references in the knot this array this is our just a lookup table but in the actual vertices array that we're going to put these values into it references the index that a particular vertices will be in so if we put this if this vertices here ends up in I don't know number 24 in the vertex array then we need to reference number 24 in the triangle array when we want to call that vertices so the way we're going to do we're going to use another lookup table we go public static read-only again because again we don't want this to change this is this is just for reference it's not actually going to do anything in the game we'll call this one box or tries new int and again we know the values Gus if you look in here we know that each face is made-up that's 1 2 3 and then 1 2 3 I'll just on the backwards a bigger the idea we know that each face is made up of six triangles one six triangle references sorry 1 2 3 1 2 3 so we know that each one of these is got each one of these faces is going to need 6 triangles and we know that there is 6 faces the top bomb back left right followed all that solving so we want it to be 6 by 6 as we've got one for each face and six triangles on each face however from now we're just going to draw sorry in an equal signs in there for now we're just going to do one face and so we need to set that to 1 because otherwise it will come up with an error occurs I don't but the rest of the faces in and we'll do the top face so 3 7 2 - seven six and again I'm not doing this from memory I am I do have this written down on a bit of paper so hmm that is currently the the only the only face in there just keep track of that that's currently the only face in there so we don't need to worry about what reference we're just going to be calling index zero and then what we will do is we will loop through these each one and then for each one of these triangles we will add the corresponding vector three from here into the vertex array so the first one is 3 so that's 0 1 2 this would be the first one that's been added and then the next one is 7 so then it would add 7 and then 2 so then it would add two remember the first first item in an index in an array is 0 right so we'll save this and back into unity not that reference thing and we need another script this one will be a regular mana behavior we're gonna call it chunk we'll get more into chunks and what they do later so in here get rid of the update for now we're not gonna be needing that we need a reference to a mesh renderer and a mesh filter we just go back into unity and I'm going to create a game object gray empty we'll just call this chunk for now and we're going to add a mesh filter mesh renderer and then we'll drag our script onto here and then link up the mesh filter in the mesh renderer so the the mesh filter basically all it does is it stores the the data for the actual mesh the the vertex locations the triangles all that kind of thing it's all starting the mesh filter when there is a mesh there this object here will have a mesh in it I couldn't give it one now but obviously we're going to be creating our own so we we don't want to put that in there and then the mesh renderers does as it looks like materials like so your textures all that kind of thing your lighting none of that's important for now so now that we've got that we'll go back in here we're going to need to keep track of the current triangle that we're on for a reason that'll be easy to explain once I've run a bit more code but let's just get this here and then what we need is an array of vertices that we're going to store for the mesh I'm going to use a list like I said this is not the way I'm doing it it's not necessarily the most efficient I'm almost certain the list is not the most efficient way to do this but it will work I think it's a little bit easier to follow along what's going on so we're gonna create a list of vector threes call this vertices equals new list vector three and then we need another list of triangles sort of in sorry for our triangles okay now we need a four loop and what we're doing here is we're looping through whichever which other one of these the minute there's only one so there's there's no question which one we're actually going to be looping through but will whichever one of these were currently on we need to loop through each int in that array so we know at the minute obviously this will get a little bit more complicated further down the line but at the minute we know that there is six in there so we don't need to worry about how long the array is because we know it's gonna be six so I is less than six now in here we're just going to add to the erase it we using this nice and simple command vertices dad and we call our voxel data class it's static so we can get it that from anywhere voxel Verte no sorry that's wrong voxel no so in here we need to get the current triangle that we're on so what we'll do is we will make a new int and we'll call it current triangle and you know what I'll call it triangle index and we'll call this one vertex index because it's probably a bit more accurate right so we'll call this one triangle index now this is going to equal will get reference to our voxel data class voxel tries and then for now we've only got one so we don't need to worry about which so we don't need to worry about which of these arrays because right now there is only one array so we reference zero and then this one wants to be I the current iteration of the loop so now we have that we just go into the vertices dot add nice handy command makes it a lot easier then try to work out where we are and then an array because this just adds to the end of that list like I say not particularly efficient but for what we're doing it should work another reference to the voxel data class this time we're going for the vauxhall verts array and we're adding whatever the current triangle says so what this line here is doing is well this one here is pulling a number out of here and then this is using that number to add one of these vertices X vertices so if the number is seven then it's gonna add this one so this is how we populate our vertices list now we need to populate our triangles list now unfortunately we can't just use any of this data because this day only this these numbers here only correspond to this we're creating a new list here and you were so we need to keep track of what triangle or on so the way we're gonna do this is this vertex index that I've created up here that I haven't explained yet we're just going to improve in Crapper we're just going to use that to add to the triangles and all we're gonna do is add whatever the current vertex index is and then after we've done that we will increment vertex index so every time we've added a vertex we add the current vertex index it starts off at 0 we add 1 and then it increments to 1 and then the next one will be 1 and so every single triangle is added in the right order and this determines the order we know that it's gonna be in the right order for we know it's gonna be in the right order because that's the way we've done it in that array so like I said the the order that we do these numbers is important and it's also for reasons that we'll be a bit more apparent when we get to the texturing part the the order that we do them needs to be the same on each face so if I start bottom left go straight up and across there if that's my first triangle then when I do the top face my first triangle again needs to be whatever the bottom left is like it let's just say that I wanted to face this way needs to go up and across in the exact same way because of the way that we're going to do the texturing like I said it there might be other ways to do it just makes it a bit easier to explain I think let me know in the comments if you think I'm wrong so if I decide I have decided and to start bottom left go straight up and then across then I need to do that on every face so that the texturing the way I'm going to do the text rim will work out so we'll go back in here we'll go back in here sorry save that now this will loop through the current triangle which is the current face which is the only face we've got a minute and it will add the vertical the necessary vertices and the triangles to the array and then what we need to do is create a mesh that we can then put that detail in so new mesh like that no cap Yolo and then we need to add our vertices list into the meshes vertices array fortunately there is a nice little added built in function on the list to just create an array and that's the vertices to array same again with the triangles and then we need to recalculate the normals I'll explain this a little bit there in a second so we do this by recalculate normals now the recalculate normals thing if you don't already know each one of these vertices has a direction there is facing so this is so that the the unis can render the light and other things accurately you start messing with the normals you get all sorts of weird artifacts and things not looking quite right and we're driving a cube so it's not really important every face like these four vertices here face straight upwards these fall here face this way and yes there are I know it looks like we only need eight vertices but there are actually each face has its own four vertices so each vertices has actually got three vertices in the same position this is necessary to draw an actual cube as opposed to drawing a sort of smooth blob because the unity will attempt to smooth between vertices so you won't get this nice hard edge if you just share all the vertices even though it feels like it should be more efficient and it probably is more efficient but visually to get this nice crisp edge of your cube you need to have vertices for every edge so this face can't share at vertices with this face otherwise this edge would be all smoothed over and I've completely forgotten why I was saying that all right for the recalculate normals so because we're just drawing straight faces got the direction of these vertices just gonna be straight up and for these ones gonna be straight forward we don't need to anything complicate so recalculate normals the built-in function is perfectly capable of doing this and then when we finally finished doing that we call our mesh filter mesh and we set our new mesh to that so now the theory if I press play we should get a luminous purple square which you can't see because of the position of the camera but there it is it's luminous purple because there is currently no texture or material data so we'll just quickly fix that for now temporarily the way we do this we need one more list this is a list of vector tools and I'll explain this a bit better when we actually do the texturing but for now I'm just gonna do something just to get rid of the horrible purple color so we're gonna call this one you've ease it cause new list vector too and then down here all we're gonna do for the time being is just add vector 2.0 and then down here mesh dot u V equals UV these dot two array and try not to press all sorts of random Keys with my fat fingers in theory that should get rid of the it should get rid but it hasn't oh right sorry yeah yes so we do actually need to give it a material so create a materials folder materials folder and then we will create a material that we will just call voxels for now I'll do and get rid of the smoothness make it not shiny because that's horrible and if we go into our chunk and we drop down this little menu here we have a material thing and just drag this into there theory that should fix that horrible purple there we go so now we have a nice white square it is drawn a 1 1 by 1 square should be one off the ground and now we have our top face so if we go back in to our cold and we go back into voxel data we can now that we know that how that works let's add the rest of these faces so again I'm got the all this written down and again is important what order you do it does make a difference what all do you do it I'm not saying that you couldn't change this order if for some reason you felt that it would benefit your code but the order is important you need to keep track of the order that you're doing the code in of course it would help if you were using the right symbols so this is the back face this is the front face and that is all of our faces so now that we have all of our faces we should be able to use this data to change our code in here a bit and draw a full cube so what we need to do now is we need to create a second loop so we'll just do this one as we call it P 4 into P equals Z 0 P is less than and again we know that this is 6 because when I change this here I will have set it as 6 so so we don't need to worry about what this specific length of the array is because we we set the length so we'll say that the six P plus plus and then and close all that right so now we have two loops and then all we're going to do here is instead of calling the zero index the first face every time we're gonna call whatever appears so all that means is there it's going to loop through each one of these and then for each one of these it's gonna loop through each one of these and then it's gonna do what we've already established it's doing so if I go back into unity we should have a full cube this time yeah there we go for each face it's looping through and it's drawing the triangles to create each face which put together makes a full cube and that's basically all the voxel is obviously it's more involved in drawing the full chunk so the last thing I want to do for this video is get the texturing working so I've got a little picture somewhere I've lost there is so to understand how textures work basically each one of the UV vector twos is a coordinate on the actual texture so the textures work 0 0 is bottom-left 0 1 is top left 1 1 top right center and dead center would be 0.5 0.5 it's a normalized value for the texture so regardless of what size the texture is 0 is the bottom left and 1 1 is the top right so if it was a hundred then not 0.9 if it was 100 pixels wide not 0.9 would be 90 pixels into the texture and the way the unity draws these textures on your actual model is that you assign a match the these vector this vector twos here correspond directly to the vector threes in here so whatever index one is of this vector 3 index 1 of this vector 2 will correspond to it and what that means is that if this one has got a UV or if the the matching UV vector for this one is as at 0 0 and then the matching UV vector for this one is at 0 1 and then the match in UV vector for the real other side of the triangle is at 1 0 then that triangle will show the bottom half or the other diagonal half of this texture this texture is the one I'm gonna use for just for setting up by the way so with that in mind go back into unity that's not unity go back into unity and we're gonna create a new folder just for textures again just keep everything nice and organized and then I'm going to drag my texture I'm going to attempt to drag my texture into there make sure everything's set right it's this texture is only 16 pixels we want we want it on clump because when you have it on repeat you can kind of get a weird little bleed edge so it shouldn't be a problem this texture because it's got a black border but when you have it on repeat you can get sort of a bleed over effect around the edges and each face that we draw is gonna want it so uncontained texture so we don't want anything bleeding over from the edges and we want point mode because just because it we're doing minecraft so we don't want everything to be we don't want unity attempting to smooth the texture out so I'll apply that now in our materials through unit is running a little bit slow at the minute in our materials we've got to voxel go to our voxels material and we go up to here and we want to set this as the texture so now whatever UV information we use on our mats on our actual mesh we'll be referencing this texture so let's let's get started in actually setting that and the way we're gonna do this is we're gonna use another lookup table now if you remember I said that I needed I needed to keep the order that the triangles were done for each face the same so the way I've been doing is I've been going bottom left top left bottom right and then I think pretty sure I've been going bottom right top left top right whatever the order is it's the same on every face and what that allows me to do is it allows me to just have a lookup table of vector tools which we're going to set up the exact same way as the other ones and then I can just call this without having to worry about which what position we are in or anything like that because everything's added in the same order so I'll be easy to explain once I've actually done it so we'll just set this up for now voxel you v's goes new vector to six again because we know that there is only six vertices in a try sorry for six triangle indexes in our face and we only need to store information for manface and then we can use it for each different face so the first each of our faces the first vertex that gets added is the bottom left so the bottom left of the actual face wants to be the bottom left of the texture and then the next one so if we go if we look at this one this is a back face we go 0 3 so we're going hero as a first one and then 3 is our second one so this 1 0 0 that's 0 0 down here the next one 0 1 so we want to add 0 1 next we'll just copy that cuz I'm lazy and then zero one and then if we look again the next one is one so one in here is this one so that's the bottom right of our texture which as you can see is one zero and so on like I said I've written all this down so I don't forget it um hopefully that's enough for you to understand what's going on I'll just add the rest of the numbers rest of the vectors so we've got first triangle and then from there one zero zero one and finally one one semicolon on the end of there so this is a lookup table for voxel UVs and then what this allows us to do instead of just adding a vector 2 to 0 we can add voxel data voxel UVs and then the current triangle index that we're using and that should give us a Oh let's just see what I've done wrong here and oh right ok and I'm sorry if anyone's been screaming at the at the monitor or whatever um unity things have been trying to for you know vector 3 so try that again when it's finished yep all right so if I press play now we should have a textured voxel there we go and all that's doing is for each face it's referencing our one our one texture that we've got here obviously things get a little bit more complicated when you want different textures on the voxel because you have to you have to work out the position of each texture within the overall texture I don't know if you ever seen the Minecraft texture pack but it's basically one big picture of lots of little 16 by 16 pictures you need to work out where in that picture each vertices needs to reference so it's easy when it's 0 and 1 0 and 0 1 and 1 1 that's that's easy enough the problem comes when you've got 16 of these and you need to divide it up I mean it's not that big a problem but it's more complicated than this so that is where I'm gonna end this video we've got one we've got one nice little voxel on the screen in the next video we're gonna turn it into a chunk full of voxels minecraft voxels that is as you can see it's drawing it all the way around and hopefully we all get a chunk a nice chunk going next time any feedback will be appreciated like I said this is just a bit of an experiment for me but for now have fun
Info
Channel: b3agz
Views: 318,633
Rating: undefined out of 5
Keywords: Minecraft, Unity 3D, Programming, C#, game development, minecraft monday, minecraft clone, c# (programming language), programming for beginners, programming language, c# tutorial for beginners, c# tutorial, unity 3d minecraft tutorial, unity 3d game, unity 3d tutorials for beginners, c# programming, c# projects, unity 3d game tutorial, game development unity, unity 3d tutorial, game development tutorial, game development for beginners, minecraft clones
Id: h66IN1Pndd0
Channel Id: undefined
Length: 35min 49sec (2149 seconds)
Published: Mon Apr 02 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.