How to Make a 3D Hexagon Grid in Godot (Tutorial)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Hey everyone! This tutorial will help you create a hexagon grid similar to hex-based strategy games like Civilization. Hope you find it helpful!

👍︎︎ 2 👤︎︎ u/josephmbustamante 📅︎︎ Oct 05 2021 🗫︎ replies
Captions
in this video i'm going to show you how to build this hexagon grid in godot 3d just like civilization and plenty of other hexagon strategy games also provide all the code in the github repo that you can find in the description below let's get started okay so you can see that i've started a blank project and that i've added a main spatial node uh just to kind of get something there so it's just a spatial node that i've called main and the first thing we're gonna do is import in our hexagon model and if you don't have one to use or if you just want to follow along exactly with the tutorial i've got one that will be on the github repo linked in the description below that you can download to use and follow along it's the same model that i'm going to be using so let me import my hexagon model i'm going to drag it right in to our project here and you'll see now there's unit hex.glb and then there's going to be the material that comes with it by default and so what i'm going to do now is actually create another node i'll hit add child node and add a spatial here and this is going to be a container for our hex tile eventually we'll have a hex grid that's going to be our entire map it's going to be our collection of all of our hex tiles but when i'm referring to an individual hexagon i'll call it a hexagon tile or a hex tile and we want to create a custom scene that's going to wrap our hexagon model that we can use for this so i'm just going to call this hex tile and like i said this is just going to be our wrapper scene for a hexagon i'm going to right click on it and hit save branches scene to make its own scene and i'll hit save just call it hex tile now i'll hit the little scene button here to go into our hex tile and what i'm going to do is actually come down to our file system and drag in our unit hex our hexagon model here just drag into the scene tree come over to our unit hacks hit the transform just reset it to make sure it's centered now this is a unit hacks it both in my modeling software and in godot i'm not scaling it at all it is just a default like uh scale of one so that's going to be important because we're going to provide a way to make our hexagons bigger or smaller later on but now that we've got our unit hex here we are good to go we've got a wrapper scene that we can instance in our hex grid so let's actually start making our hex grid in order to do that we'll come back into our main scene so i'm going to select our main scene hit command a or control a if you're on windows to create a new spatial node and similar as before i'm going to call this hex grid because like i said this is going to be our entire map our entire grid of hex tiles i'm actually going to delete the hextile we created before we don't need it anymore and then in hex grid i'm going to add a script to it we'll just call that hexgrid.gd and we'll be good to go let me get rid of a lot of the boilerplate here and what we're going to start off doing is within our ready function we are going to call a function which we'll create in just a second called generate grid and let's actually define generate grid now you'll notice that i've given it the underscore in front of it which in godot is kind of the syntax to denote a private method that is a method we don't really want anything outside of this script to call so we'll create a function with the same signature generate grid and for now we'll just say pass we'll come back to that in just a second and start adding code there but first let's define a couple constants first we need to get a reference to the actual hexitile scene that we just made so we can instance it in our game we'll say const all capitals hex tile here and the reason i'm doing constant is because this is going to be a constant reference it's not going to change and with just it's a common syntax that whenever you have a constant value saved as like a field or as a member variable of a script or a class you want to uppercase it just so that it denotes anywhere else you use it hey this isn't going to change it's just common syntax that lets any user working on your code to know that this is a constant value so we'll follow that syntax here and then we'll say equals and then we'll preload our hex tile and we can preload because again it's a constant path we're always going to be using this hex tile then i'm going to create a new constant right above it and i'm going to call this tile size now what this is going to be is it's going to be the scale of your hex tile remember how i said that my tile wasn't scaled at all we're going to be using 1.0 and it's important to make sure it's a float here so that godot will try and use float math instead of integer math and it won't truncate things now if you want to scale your hexagon tiles up individually you want them to be a bigger size you can use this variable to do it there are also ways to get this tile size programmatically rather than hard coding it but just for the ease of doing this tutorial we'll hard code it as one for now if you're unfamiliar with this colon equal sign syntax that's just telling the godot interpreter what type it is it's telling godot to infer the type of this variable from the default value i give it so since i say 1.0 since i give it a float value by default the godot interpreter will sit we'll see that and be like oh okay this has to be a float variable i'll make sure that any any value that tries to get assigned to it is a flow as well of course it's a constant so we can't assign to it but just a quick rundown of that syntax okay so now that we've got our constants set up here we're ready to actually start generating our grid actually that's a bit of a lie we need one more variable here and we're going to make this an export variable and this is going to let us determine from the editor how large our grid is going to be again just for the sake of this tutorial i want to just do a square grid so if we define a grid size of five it'll be five hexagon tiles wide and five hexagon tiles tall it'll just be a square grid you can modify this on your own later on but for now we're just gonna do that so let's define that variable we'll say export and we want this to be an integer because we want it to be just a square number and i'll say between 2 and 20 for now just to give it a type hint to make sure that we don't have grids that are too small or too big i'll say variable grid size and again i'm going to set this equal to we'll just default it to 10 for now okay so now we've got our constants and our grid size variable set up let's actually start coding and the way that we're going to create our generate grid function is by pretending it's just a square so we're going to do a for loop going through the rows and a for loop going through the columns we're going to start by doing the columns first so i'm going to say 4x in range if you're not familiar with range it's a function that returns an array of the numbers leading up to the number you define so i'm going to pass in grid size here so if our grid size is 10 this range function is going to return an array of the values 0 through 9. so it's going to loop 10 times so we'll do 4x and range grid size and then again we'll do 4 y and range grid size 10 columns and 10 rows per column okay and we'll come back and add some more code to this later but now that we've got our general uh our general for loop set up we can start adding the actual instancing of our tiles so we won't worry about the actual position of our tiles for now we'll start by just instancing them so first we can get we can actually instance our tile since we have our hex tile pack scene saved into a variable we can say variable tile we'll just call it that and this will be hex tile dot instance because it's a pack scene we can just call instance on it and now we will have an instance tile now all we have to do is add it as a child and note that this script is attached to our hex grid so it's going to be added as a child to our grid and not to our main scene and now we're going to add a new tile for every tile that needs to be there as part of our grid the problem is that they're all going to get instance on top of each other right now so now we need to do a little bit of code that will help us to move them apart first let's in order to do that let's create a new variable and this is going to be a variable that keeps track of the current coordinates or the coordinates of our current tile it's going to keep track of where our current tile should be instanced in the game world so in order to keep track of the coordinates for our current tile let's make a new variable and we'll call this variable tile coordinates just so it's very clear what it's doing and we're actually going to make this a vector 2 and default it to vector 2.0 so it'll be a vector 2 of 0 0 and the x and y and you'll notice that we are doing everything with x and y coordinates in a vector 2 right now and but we're going to be actually you know creating our grid in 3d and so the way that's going to work is our y coordinate is actually when it comes to 3d space gonna be our z coordinate because in 3d we don't want to move a hexagon tile up or down in the y axis like this we instead just want to make sure that we are translating our y-axis of our tile coordinates into the z-axis of our 3d world when we're actually instant or moving our tile around okay so let's start just with the simplest thing in the inner loop going from row to row so we're not going to go column to column yet we'll just build things within the same column so we'll just pretend x is always 0. it's always our first column and we are going to build our first column by going row to row here so what we need to do is imagine we instance our first hexagon right well we need to move that the next hexagon down the full height of our first hexagon and it's important to notice too if you look at the hexagon tiles we're using that the faces the two flat faces are top and bottom the top and bottom aren't edges or vertices they're not the long diagonal here they're two faces and so what we can do then is just make sure that we're moving down the full height of our hexagon tile and that'll get us to our next one so what we're going to do is say tile.translate because we want to translate our tile down and we'll say vector3 so we're going to create a new vector3 and for the x-coordinate of our vector3 we want as you'd expect tilecoordinates.x because we want it to be in the x coordinate of the tile coordinates of the coordinate it should be at and remember we said we're not going to do anything in the y plane for our vector 3. so this is actually just going to be 0 for our y value and for z this is where we're going to translate tile coordinates dot y into the z axis of our 3d world so we're going to translate our tile to a certain amount in the x direction and a certain amount in the z direction according to whatever our y coordinate is for our tile now you could skip the whole vector 2 to vector 3 thing and just do all this in vector 3. i just figured i'd do it for this tutorial in the hopes that it'd be less confusing to first think about our hex grid in a 2d space and then translate it to 3d but if it's a bit more confusing don't even worry about it just do it in 3d in your own game okay so now we're moving our tiles correctly but the problem is that we're never actually changing tile coordinates so whenever we move a tile down to the place it needs to be we need to set the tile coordinates for the next tile to be one tile down so in order to do that all we have to type is just tile coordinates dot y and plus equals tile size this is where our tile size variable is going to come in handy because like we said before we're just moving our hex tile a whole unit down a whole tile down and so now each hex tile that we build is just going to be one tile down and we can actually run it now and see that even though we're only going to have one column we can actually see that it's building correctly in order to do that we'll have to come back into our main scene and add a camera so i'll do that right now and we'll just do a simple top-down camera so if i come into our transform here i'll rotate it negative 90 degrees in the x direction this will make sure that the camera is oriented facing straight down as you can see right there and we'll just move this up a little bit so i will say up by five units and now if i run our game hit command b or control b you'll see that we have a column of hexagons this is great it's working exactly as we expected it looks like they're the connection between the faces is that the right amount the problem is that we don't have any other columns so that's what we can work on now first let's adjust our camera a little bit just so it's a little bit easier to see what's going on i'll move it over 3 and the x and 3 in the z direction just so that it's a little bit more centered and if i run this now we should have a bit better of view again i'm not going to build any custom camera control just for this tutorial so you can move your camera around as needed okay so before we actually get to making new columns let's just very briefly go over the math involved just so you kind of understand where we're getting the numbers we need from i'm not going to go totally into this and you can skip this part if you just want the code but just wanted to give a bit of an example in case people are curious so in godot when we say that a hexagon has a size when we say it's got a scale what godot is really looking at is this line right here it's looking at the length from one face to another face but this length from one face to another face isn't actually the same as from one vertex to another vertex that's across from it they're slightly different and in order to figure out what that difference is you all we really need we don't actually need the actual amount the actual length of this here but we do need to find the ratio so that we can multiply it by whatever our size of our hexagon is so this is the column we just built right and if we want to find this value right here if we want to find the x value to the right to build our next column we need to figure out what the relationship is between this size and this size right here and in order to do that we can take advantage of the fact that hexagons are actually just built of six equilateral triangles which you can see me sketching out right here i won't keep going with that because my drawing is terrible but you get the point and so if we want to figure out the relationship between this side and this or this line and this line we can actually just do it by finding the relationship of half of those lines this and this and in order to do this relationship you can see it's a right triangle right here oops that was supposed to be supposed to be square with we can just find the relationship of the sides of this right triangle and if you remember much from your basic trigonometry class you'll remember that if you want to find the relationship between the adjacent side of an angle which is going to be this if we're using this 30 degree angle right here if we want to find the adjacent side of this angle we can take advantage of the fact that it has a constant relationship with the hypotenuse of that same triangle and we know that that relationship is that the cosine of 30 degrees of this angle right here determines the relate the ratio between the adjacent and the hypotenuse sides of this triangle so again we're not getting all the way in and breaking down what these sides are but just showing that this cosine of 30 is is the value that determines the ratio between these two sides and not just these two but by extension these two here which is what we want when we're moving from this point here and trying to find this point it's this distance and this distance so we can actually take this knowledge now and apply it to godot but before we go back to godot remember not only do we need to know cosine of 30 or sine of 60. you could do the same thing with this angle here but we'll just use cosine of 30 because we already talked about that not only do you need to know the cosine of 30 we also need to make sure we pay attention to how hexagon grids are laid out you'll notice here that this grid is not this hexagon right here and then another hexagon that is that is at the same x value as it instead there's an offset right this hexagon is actually moved up this way so when we're doing our hexagons we're seeing that our hexagons in the same column their faces touch each other but hexagons in another column they actually have a diagonal face not a flat face that connects it there so that's important to know is our r or our columns are going to be staggered a little bit because hexagons don't connect by touching vertices right here it's not a connection like this but rather a connection like we have here so just remember we need cosine of 30 and we need to remember how a hexagon grid is laid out and if you have that we'll be good to go back to godot and actually implement this okay so first we'll use the cosine of 30. remember that we said this is the ratio between the sides so we know that if we have a tile size of one and that this side this tile size is determining the length of a line between one face to another face that if we want to find the length of a line that is a diagonal to a diagonal we need to use the cosine of 30 to get that and so what we're going to do is say tile coordinates dot x and remember we're going to be adjusting our x value here because we are trying to build the column to the right of the previous column we just did so tilecoordinates.x equals and here we're going to do x because we want the current column right if we're on the fifth column we need to adjust relative to how many columns have come before so we'll say x and then times tile size and this is because if we scale our tiles up we want to make sure that we space out our columns appropriately so this will just make it scale proof as our columns or our tiles change size so we'll say x times tile size and now the important part times cosine of degree to radian of 30. and the reason i'm doing this is because the cosine function in godot and all the other trigonometry functions take radians as their input but just for the sake of this tutorial i'm just going to call degrees to radians which is a function that will convert from you guessed it a degree value to a radian value here and so what this is going to do like i said is it's going to build a new column and remember this line is only getting run when we build a new column it's only getting run during the first or when we move to a new column it's going to start that column at a relative position based on the scale and column index that we're on and then move it over the correct amount based on the ratio between our tile size and the line that we're trying to go the line between two vertices so we can actually run our game to make sure that this is working correctly and if we do we'll see that all of a sudden we've got multiple columns so this is looking pretty good except remember how we talked about how hexagon grids need to be laid out and you'll see that we haven't actually staggered our grid yet but in order to do that it's very simple we're going to add just one more line here and we're going to say tile coordinates dot y and the reason for that is because remember we're staggering in the y direction or in the z direction in our 3d world and we're going to say tau coordinates that y is equal to and here we're going to use a ternary statement so we're going to just do this all in one line and we'll say tau coordinates that y is equal to 0 if and what we're going to do now is say x modulo i'll explain this in a second x modulo 2 equals equals zero and so what we're doing here is we're saying if x modulo 2 equals zero and if you're not familiar with modulo it's getting the remainder basically what x modulo 2 is doing is saying is x an even number so if x is an even number it won't be staggered but if x is odd we'll say else and here we want to stagger this by half the size of a hexagon remember in that grid we've just looked at it's half of our tile size so we'll say tile size over two so if it is an even column no stagger but if it's an odd column we stagger it by our tile size over two now if i run our game we will see that we've got a hex grid and it looks exactly like we would hope it would okay so off camera i created a few extra materials that are just basic flat colors blue green red yellow etc and added a simple function that just keeps track of what index of tile we're on whether the first second third fourth or a hundredth tile and basically just pulls a material that's appropriate to that if you want to get this code you can either copy it right now it's pretty simple or it'll be in the github repo for this project again in the description below but the main thing if i run this now you'll see that our finished product looks just like this so again it's nothing too fancy but we have a hexagon grid it's just like they make in civilization five or six or any other hexagon-based strategy game and it's relatively easy to make and we did in godot in 3d so i hope this tutorial has been helpful for you if it has a like and subscribe to support the channel are always appreciated we'd love to have you in our discord server feel free to ask any questions there link to that is in the description below and would so appreciate if you donated to my channel and buy me a coffee the link to that is also in the description below thanks so much for watching i'll see you in the next video [Music] you
Info
Channel: jmbiv
Views: 1,261
Rating: undefined out of 5
Keywords: godot, godot engine, godot tutorial, how to make a game in godot, game development, game development tutorial, game development for beginners, godot for beginners, game dev, indie game dev, indie game development, hobby game development, gamedev, godot game engine, jmbiv, hex strategy, godot hexagonal tilemap, godot hex grid, godot hex tiles, godot turn based, godot turn based strategy tutorial, godot grid, godot strategy game tutorial, godot 3d, godot 3d tutorial, godot 3.3
Id: 3Lt2TfP8WEw
Channel Id: undefined
Length: 21min 58sec (1318 seconds)
Published: Tue Oct 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.