Create a Hex Tile Grid in UE4 and C++ [UE4 Tutorial]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and today we're going to be having a look at creating a hex based grid uh as a foundation for any kind of hex based tile game that you're looking to make uh so um hopefully this will allow you to create something similar to this is a game that i made recently for a game jam that's based on the the same kind of basics that we're going over today where you can just build up a world made out of these hex tiles and then you can customize each tile and uh yeah you can be creative with how you want to get have your world generated and the likes but uh yeah we're gonna be doing it from scratch um a new unreal engine project um so let's get started so i'm using version 4.26 it should be fine in any version to be honest we're not using anything too fancy in here and if we just go ahead and start a new game uh you can start with a blank project and we're gonna go into c plus um and i'm just gonna give it a meaningful name so i'm just gonna call this hex tutorial for now press create project it should take a little bit of time to just to get started and it should hopefully open visual studio for us um and then it will also open up the editor first as well so um one thing i will get up on screen ready is a resource that's super useful and that we is going to be good if you're going to carry on to make a hex based game after this kind of introduction then this website is uh something that really goes in detail over all of the kind of maths or the kind of rules you use while using a hex based grid um and so yeah it is uh redblobgames.com grids slash hexagons um but yeah i'll refer to it once or twice during this but i just wanted to make sure that um you people are aware of this and you can open it alongside if you want to reference it yourselves okay so uh it's generating the game code it's going to take a little bit of time now but what we we're hopefully going to get by the um end of today's video is you're going to be able to have a scene in unreal engine where you can add in what we're going to call a hex tart manager uh you can tell it how many uh or how wide and how tall you want your hex grid to be um and then when you start the game it will create that hex grid for you um and then you'd be able to to build on top of that framework so we have the editor uh as opened and we also have our visual studio opened here so let me just get this night open up for us okay lovely okay we don't need to uh specifically do any code right now because we need to make some classes first uh first thing we're gonna go ahead and do then um is we're gonna create a couple of folders just to keep our working a little bit tidy so first i'm going to open up this uh the the file view i prefer working that way and then we're going to go ahead and just make one folder for the levels because we're going to make a new levels a level sorry and then we're going to we can probably make one for that blueprints that we're gonna create during this as well so in the levels folder we're gonna first add something so we're just gonna go file new level and here we'll go with the default one and then ctrl s here to save i'm going to go into my levels folder and we're just going to call this our x grid level it's no problem okay so this is what we've got at the moment very little in it but it doesn't matter for now the one thing i'm going to do quickly before we get into anything is all these kind of base things that are in here by default i'm just going to shift them along a little bit uh just so that they don't clash in the way a little bit later so i'm just going to select the light source atmospheric fox guys here skylight and the sky reflection capture and we're just going to chuck them in their own little folder i'll just call these the environmental things um and i'm just going to whack them all on the same location as zero zero zero you don't have to do this i'm just doing it to try and make it a little tidier later when i'm explaining so just put them at zero zero zero and then we can just move them away a little bit that's no problem yeah so there we go we've chucked them out let's check them at one thousand that should be fine okay and then we've got our player start as well um in here that's fine and we've got some flaw we'll probably delete that in a bit but that's no problem so uh yeah let's get started let's make two classes then um i'll just press ctrl s to save my map and then we're going to go into our blueprints folder actually no we're going to create the classes first um so we're going to go you can go in to see your cpp classes down here and right click and create a class you can do it from file create class as well if you want new cpu class cpp class so first off we're going to create a new one these are both going to derive from acta the two classes we're making so the first one click actor and then give it a name we're going to call this our hex grid manager i'm going to create the class it's going to take a little bit of time and it'll probably open it in visual studio as well uh so this is going to be our thing that manages the the spawning of all of your hex tiles and manages the logic that says how many rows and columns and how far they should be spaced apart and the likes so it's not going to have a physical representation itself but it's going to be the actor that spawns in all of the the tiles that we're making the hex tiles so there we go we've got this class made i'm just going to go ahead and create one more quickly so the second one we want to make is going to be again deriving from actor and this is going to be our hex tile so let's go ahead and create the class there and again it will take a little bit of time and then it will open up in visual studio for us so uh we'll we'll get started with this hex tile because this is going to be essentially the foundation of what this is based on right it's a tile based game each of them are going to be hexagonal and so we need to create what a base tile is i'm just going to click reload all here okay bro so um now that we've created those i'm actually going to go ahead and close the editor because we'll relaunch it once we've done a bit of code now so i'm going to close the editor down and now we can get started with our code so first things first we don't actually need i'm in hextile here i'm going to just i'm using visual assist so if my code looks a little bit different to yours um don't worry about it um but i i don't want to go over the nuances of visual assist now but um it will allow me to use some shortcuts that maybe you can't but you should be able to get around it yourselves it's not a problem so uh we want to go into um the cpp of this so i'm just going to go ahead and open that up so i'm in the hexatile cpp now and what we want to do first is get rid of this tick and begin play we don't need to use those okay so we're fine just to have a constructor in here i'm going to go in to my header and i'm also going to remove those because we don't need those okay so what do we need so first off we i'm going to create a couple of members um and then i'm also going to create an enum to represent a type of tile so let's say that this is going to be a world we're building we might have some grass tiles some mountain tiles some water tiles and the likes so i let's go ahead and create an enum for that first so i'm in the header for hextile and i'm just going to declare an enum in here so let's make a uinum uh elem class a hex tile type so the type of tile that we're going to be using um and then we're going to go and define the different ones now so first off i like to do invalid as the first one just so you don't accidentally you know if you haven't selected a value for this wherever you use it and then i'm gonna do grass and water for now you could have more it's up to you but we'll just start with those um and then i tend to finish off my enums with a max value as well which won't show up in editor if you add that bit of code okay so we've added our enum so we're going to go ahead then and set up a member which will hold that that tile type so um i tend to do all my members at this at the top and then all my functions at the bottom so that's why i'm just going to make a new section up here so i'm going to make a protected section here uh for my protective members and this one is going to be you property because we want to expose this out to editor we're going to make it so it's uh edit defaults only we're going to make it a blueprint read write uh i don't actually you probably read would be plenty but i'll just let's just do read write to be safe and then we're gonna go category i'm just gonna give it a category of time okay so then i'm going to give it the actual type which is that enum that we've just created up top and then i'm going to give it its name which is going to be title okay so this means for ex every tile that we're going to create we can give it a type so it can be a grass tile or it could be a water tile or however different ones you want and the idea is we'd make a blueprint of the different types and then when we spawn them in we can choose from those different blueprints which ones we want to put in so we're also going to do we need a physical representation of for this tile now so we've got a data representation of what it is but we now want to go ahead and do make a static mesh so we can physically see the tile right so that's the step that we're going to take next um so we're going to use a u static mesh component um i'm happy for this to be the the same uh the same uh you property details for now it's not massively important for the purpose of today and then we're going to just call this tile mesh okay so we've got those uh that has been set up and i guess for now uh let's have a look at what that looks like so we can go ahead oh actually with the thought we probably need to set it up in the cpp as well right so we can actually spawn this yeah let's do that before we launch the editor so um yeah for we we don't need this tick so we can get rid of this i mean or you can even set it to false but i think it's false by default right so you can just get rid of that uh so the two things i'm gonna do um i could just spawn the the tile mesh so let's go tarmesh equals create default sub object uh and then this is going to be of type u static mesh component and we'll just give this a name uh which is going to be our tile mesh for now okay so we could just do that but um what i like to do is because we we might want to move if you do this the the tile mesh will become your root component of your actor and we may want to move this this mesh around and so i'm going to give it a separate root component instead so the root component uh already exists as a part of acta and we're just going to create a using component for this just so that we have something that is our root component that isn't our mesh okay so this will be a using component and then we'll give this uh a name like we have root con okay good and then the final thing if we're using a different root component we then need to set up the attachment so we'll do tile mesh and then we're going to go to setup attachment and then we can put in the root component so that'll mean that it'll be attached to it excellent okay so that's pretty much all we need to do here we need to do some includes um as well uh i've got some fancy shortcuts for this um oh if visual systems working i could but okay um yeah you can just manually do the includes yourself then my visual assist isn't working after all that talk earlier so we want to go ahead and include some components folder because these are based on real things uh scenecomponent.h that's where that one lives and then we're going to go ahead and do uh components and this is going to be for our static mesh component dot h okay so there to click there let's make sure we uh in this um header i've just jumped to we're probably going to forward to clear this as well again is this yeah it's not working for me so i'll just do my four declared separately so um i'm gonna go ahead here and just say there will be a class defined as a use static mesh component like so all right uh that should do it for this so we're gonna just do a quick compile make sure that i have made any mistakes which is perfectly feasible i may have yeah there we have oh yeah we missed the pointer yeah there we go okay so hopefully this time i'm going to press f5 because hopefully that's the only thing that was wrong there f5 will launch the unreal editor for us as well yeah there we go so it's compiled nicely and it's just launching the editor for us now so um what we're going to have now is we can create a blueprint of that actor um uh but we don't have a mesh for it so we're gonna quickly make a mesh for it as well let's go ahead and jump into that level we had um let's first go into our blueprints folder we're going to make a new blueprint based on that class that we've just written right so blueprint uh instead of doing it from one of the base ones we're going to go ahead and look for our hex tile that we've just made so we've gone into hex hextile select we call this bp underscore hextile we can jump into that then drag this window up here and yeah at the moment you can see there's the root component that i made earlier and then we've got our hextile mesh but at the moment you can see we can't actually see anything here because we don't have a mesh associated with it so uh we need to go ahead and make a um a hextile and i'll just do it really quickly in blender if you haven't got blender it's free so just download latest version of blender and you can do exactly what i'm doing so let me just open blender i'll move it across then so you guys can see okay so uh you can just press well escape on that we need to close that delete everything that's in your scene so we don't need the camera cube or the light uh and then all we're gonna do is make a new thing we barely have to use blender at all so shift a brings up the add menu in mesh you can go down to cylinder and then on this little box down here if you press the little arrow it'll open up properly and we want to say um how many vertices is going to be that make up this cylinder uh if you think a hexagon if a 3d hexagon at least here is going to be basically a six sided cylinder so if we give this uh six instead here you'll see that it changes to look more like a hexagon you can use your middle mouse to move around to check the shape of it if you want i'm happy with it being having a radius of one that's the kind of size of it um and then i'm going to go ahead and just set this to 0.25 just so it's a little uh it's got a bit of chunk to it but it it does look more like a tile now that's uh fine for me okay so i i can now go to file we can now go to export and i'm going to do it as an fbx and then i'm gonna put it in the location of my project so uh i'm just gonna go to my specific location where i've got my project set up uh you'd have to go obviously to wherever your project is set up so mine was hedge tutorial into the content folder and then i'm just going to save it here so let's give it a name and this will be our hex tile for example so let's press export and the nice thing about unreal is unreal will detect oh you've added a file into your content folder do you want to import it as an asset great so let's press import we don't really need to change anything in here so let's press import and now we will have an asset let's go and have a look so if i go to content browser uh let me just save that blueprint and we go into the main folder we now have a hex tile here excellent i could drag one of these in that's just the mesh of it though remember so we're not gonna drag one in but what it does mean is now that i can go ahead and i can set the mesh to be my hex tile here you can type it in if it doesn't show up there so there we go we now have a tile asset which is good um so if i go into my blueprints we now have a bp hex tile i can drag one of those in instead and there we go we've got our first hex tile we can make a control w we can make multiple of them if we want now the moment you notice they don't have a material so i think uh a sensible thing for us here is to probably make some materials just i remember when i was starting off i didn't actually have any knowledge on materials and it always made me a little bit uh frustrated that it seemed something so simple i just wanted to give these colors you know so let's go ahead and make something simple just so we can assign colors to our tile shall we so we're going to make a new folder in here we'll call this materials uh first off we're going to make like a master material it's nothing too complicated here it just makes making different colors easier as we go on so uh we're just going to call this m underscore color base we're going to go into this and effectively we want to make like children of this material but we don't have to come into this graph every time to set up the colors and any um maybe we want to change the metallic specular or roughness of it as well three common things that you might want to change about your material so what we're going to do is just expose these out as parameters instead so that our child classes of this material can just have easy access to them so let's go ahead and do that for all of these i'm just going to drag them across so it's easy to see right click promote parameter uh for all of these first four and then i'm going to set some default values for them so for the base color uh let's just say it's something obvious so we know if we haven't set the color so it'll be nice and pink to begin with um and then metallic over down on the bottom left is here we'll set the the default values for it so i'm okay with metallic stainless zero specular can stay at zero and roughness will put us like 0.5 for now let's just have that as our kind of base material so we save that and now we can make material instances of that that's the kind of sub or child classes of this material that i was mentioning earlier so i can close that down and if you right click on your material create material instance we're going to call this mi for material instance and then i'm just going to call this color green for example all right because we're gonna have a grass tile right so if we go into this now instead of having to go into the graph i can just tick the base color box i'm gonna say right um i want this to be uh a shade of green so you can do whatever color you want let's go for that okay so we've got our green color here let's go ahead and save it um and let's make uh one more color shall we so ctrl w on this to duplicate it i think instead of green this is going to just be called blue um and this time we will change it to be blue for our water tile so that looks fine to me now what i might want to do on this as well is because it's water we might want to say okay actually you have a little bit of uh instead of having zero specular you might want to take this up a little bit so let's put this as point five so there you go it has a little bit of shine on it there and we might make it a little bit metallic as well just to make it look that a little bit more like a shiny surface but that'll do for now so we've got those two materials now that we can use so this tile that we've made this is going to be our like our base tile that we can do any logic in here um that we you might want to do in the future um so i'm just going to assign this not a grass or um water i'm just going to give this the base color that i made earlier this pink color because we really we're not going to be adding this tile into the world we're going to make subclasses of it so we're going to go ahead and do that now so you can see these two here let's get rid of those let's go back to our blueprints folder and in here we're going to make a child blueprint class so we're going to make one of them which is going to be hex child sorry hex tile and instead of calling a hexagon it's called child class we're going to call it underscore grass let's go into this and i can all i need to change in here then so first off we're going to go and have a look at the mesh we're going to change this to be the green that we just made like so and the second thing we want to change about it is if you remember we had that tile type didn't we that we declared in the code earlier so remember this tile type and we exposed it out here yeah so we're going to set that to be the grass one that we we set up earlier so let's go ahead and do that so this is grass compile and save that and then let's quickly do the water one as well it's not going to take any time control w to duplicate that we'll call this water go into this one we need to change this to be water um and then we're going to go into the full blueprint editor so i can just select the tar mesh and we're going to say the blue color for that one excellent so that gives us now uh two different tiles that we can use obviously you can think about how you want to do this yourselves but i just wanted to to give a very simple example to begin with so um now that we've got these we should be able to just add them into the world and start thinking about hex layouts a little bit so uh let's add in a green one let's add in a blue one so we've got two tiles um and we need to try and think about how we're gonna kind of lay things out um because hex tiles are easy if you're using squares right because it's the same distance um horizontally each tile is separated by the same distance horizontally as it is vertically however with a hex grid remember the website i showed you earlier it has a bunch of examples that you can look at you can see that it's not quite set up that way then there's a bunch of different ways that you can set up your your hex grids but ours is going to be the pointy side of our hex is going to be pointing up and every second row is going to be like shifted in 50 so you can see we have this is our first column this is our second column and then the rows are quite standard straight across okay but because it has this slight different non kind of uniform pattern because it's different every odd row uh we're gonna go ahead and kind of think about the the locational differences between these tiles now so let's go back and have a little look at what we've got so let's put the first tile at zero zero to begin with put that as zero zero zero and we'll put this one at zero zero zero as well and we'll get moving it i'm just going to move to a top down perspective for a sec to make it a little easier to see uh what with what we're working with so they're both on top of each other at the moment we've got hextile grass hex top water here so i'm gonna just move one of these so remember x is your like left to right and then you've got your wires you're up and down um in this view so at our if you remember we when we made this in blender we we gave it a size of one i can close this now we don't need blend open anymore you can save it if you wish i don't i'm not going to um we've exported the fbx and that's what we needed so we don't need a blender file for it if you're new to blender that's all that was asking so um yeah we have a size of one and what that means is uh the full height of it is going to be twice that amount so this here if i right click you can see a little ruler comes up a middle click sorry and you can see that the the height of our tile is 200. uh and we can verify this by some of the maths set up here you can see here that it will say so the height of the tile is uh two times the size okay cool so the size was 100 earlier and uh it was one but that is in one meter and in unreal we work in centimeters so uh one in blender equals 100 in in unreal so that's why we've got um a size of 200 here okay so uh yeah this is telling us that our hexagon the height will be two times whatever the uh the size was uh and then it says the width is slightly different you notice it's not the same shape uh it's not the same width as it is height it's a little bit narrower and the rule here is the square root of three times size like you don't have to understand this if square root means nothing to you don't worry about it uh it's just there is some maths behind this rather than us putting in magic numbers i wanted you to kind of understand why we're putting in certain numbers here so what that means then if we go back to unreal is if i wanted to move um remember i got two tiles on top of each other here if i go into the location here and i say right i'm going to move on the green axis the y axis here um we know that this is 200 tall so if i add 200 here we can see that one perfectly lines up below it let's change it to lit as well so the colors are a bit clearer for you to see okay so you can see that we've moved it bang on to the bottom of it that's nice but that's the thing with hexagonal tile grids is the layout of it is actually going to be different they're not going to be top to bottom like that if you remember the top of this one or the bottom of this one connects with the corner of the one below it which is shifted across a little bit right okay so uh but we know that the height of it is that and if we wanted to know the width of it uh let's move this one back up to zero so it said if you remember earlier let's get the calculator open okay i've just switched to scientific mode in here um if yours looks different to mine but i said the square root of three right so if we go three and we press the square root button here okay that is the square root of three and then we want to times it by the size which was 100 if you remember so i'm just going to do times 100 that should be how wide our tile is so let's go ahead and check that we might have some rounding issues um or where it gets trunk uh like truncated somewhat but it should pretty much be accurate here right so let's take that number and let's put this in the x axis to move it across so if i put that in there just ctrl v to paste in you can see now we can perfectly move to the side so there is like maths behind how like wide it is and you can use that as part of your calculations to build up this hex grid so that's how we would set that up let's try and think so moving across the width of it is going to be just this right if we wanted to set up tiles that are exactly right next to each other so if i wanted to add another one onto this um i would just go ahead and let's change this back to zero um and then i'm just pasting in the number i can put times two and that'll move it across a little bit oh i'm not sure if i made a mistake with that value in there uh let me go ahead and copy it from here again get that at the way let's put that value in yeah that moves it going on top of it if we times that by two now there you go that's what i was trying to do there so it just moves it across so you can see we can just times by that amount to to kind of fill across in that direction so let's think about that next row then so how far down do we need to go in order to um to do this this second row let's look at the diagram again to do this second row here okay so there is information all the stuff i'm telling you now is pretty much found in here right so you can find out this uh information here for example so the horizontal distance between adjacent hexagons horizontal this side this uh side to side kind of distance is going to be the width which was that weird number that number that we put in earlier great so the vertical distance is going to be the height times 3 over 4 which is 75 of the height right so the height if we remember was 200 earlier so if we type in 200 and we times it by 0.75 that will give us 150 so we know now that it's going to be 150 units down in order to go one row below so let's go ahead and do that i'm going to just duplicate this grass tile we'll reset it back to zero zero and then i'm gonna add to it uh 150. and there we go it's moved it down and you can't it you don't know if it's in the right spot yet but if we move it across you can see it does just fit it is the right height for it now it's snapping a bit on when i'm moving it across so it doesn't look like it's fitting in perfectly but you can see there it would fit in lovely there okay so we've got the height now we need to work out this gap so that's the thing with these hex grids uh the kind of you need to add an offset for every other row so it's going to be the same distance between each one so we're still going to use that that square root of 3 times 100 between each uh each tile on each row but depending on if the row is odd or even or every other row if that's easier to think of we want to add an offset and the offset if you think about it is just half of one of these hexagons and we know the width well we worked out earlier right i can click on this we can just borrow the value from in here so this was our square root of 3 right so if i just go to we'll do it again square root of 3 and then we times it by 100 gave us that value right so if we copy that what we want to do is is basically just half that so uh i can times it by 0.5 or divided by 2 what if i prefer and there we go we got half of that value now so uh i can go ahead and we can write that in the uh x here to shift it across what we should find is now it falls right into the right position so we're doing it exactly snug where they're right next to one another and if we change back into perspective view it may not look exactly the best sometimes it's nice to actually see the tiles so if you want you could always add a little bit of gap between them but the nice thing is what we're going to do we're not going to manually build this up our hextile manager class that we started making earlier we're now going to work on making that automatically spawn these with the right distances in between but the important thing is here now we understand that there's different bits of maths that we need to understand we need to understand how far how wide a tile is how tall a tile is um we need to know the offs uh like the horizontal uh gap between tiles when we're spawning them so we know that there's a tile width between each one of these uh we also need to know the vertical gap which was 75 percent of the height so that was 150 units down and then we need to know for every odd row the placement of it is going to be offset in the in the right direction by um half of the tile width which was around 86.5 ish in the end so now that we know that that will help us understand what we're going to be doing in this next step so let's get to it then let's make the thing that's going to spawn this automatically for us i'm just going to go ahead and select all of these we won't delete them we'll just move them out the way somewhat just so we can refer to them later if we need to okay back to the code then so earlier we made a hex tile but we also made a hex grid manager and at the moment we're gonna have just two empty files that we haven't done so i'm in the cpp of it here and then i've got the header of it here now we don't need the tick in this one so let's go ahead and delete that first before we get started so i've deleted it from the header there and i'm going to go ahead and delete it from the cpp and i'm going to tell it that it doesn't need to tick as well for that reason great okay good start so uh the what we're going to do first is we we need to create a two-dimensional array because we're working in a grid you'd do this if you're doing a square grid as well um is generally the way that people tend to represent it is a 2d array so that means that you'll be able to access it by doing like my 2d array whatever you call it and then you can give it your x-coordinate and you can give it your y-coordinate and that will allow you to to reference thing things by their kind of x-y coordinates which is a bit more natural to do and it makes it quicker to access what you want to do when you know the exact location of the tile or the coordinate of the tile you can just access it in the array in this easy and kind of nice to read way so we're going to make a 2d array for this we're also going to set up um some variables that we can set up on this manager in order to denote how wide and how tall we want our grid to be so let's get started with that like i said i like to do my member variables in a separate section uh so for that reason i'm just going to do a new kind of protected area up here and then we're going to get started with writing some of these out so first off let's do the the easy stuff so you properties uh these are gonna be edit anyways so if you don't know the difference between edit anywhere in edit defaults only that we did last time edit anyway means once we've added the blueprint into a level we can change the value as well and we want that for this so we can tweak and play around with it in the in the world uh i'm just going to give this a category of hex grid okay uh and in here this is just going to be an n32 and it's going to be our grid width so how many tiles wide we want right this isn't like a a size thing this is how many individual tiles do you want we're going to do the exact same thing for the height as well so let's just copy paste to that in and this is going to be called grid height so yes i might actually put these in a nicer uh setup thing as well just as this a nicer practice in my opinion so this will be in the subsection of grid height uh sorry of hex grid which is going to be called our layout let's say okay so let me just copy that uh copy that into both of these okay so we've got our grid here area grid width and we've got our grid height i'm also going to add in here that two-dimensional array set so it's a t-array and inside that t-array is another t-array and it's going to be holding pointers to the tiles that we've made and if you remember our tile class is a hex tile so we add the pointer there we go bit of a a mess of symbols that's what you get with a 2d array okay and we're going to call this our hex grid uh 2d array okay so uh that's where we've got started with what we're going to now go into the cpp and see what we can do with this starting point so in our begin play we're going to go ahead and we're gonna we're gonna essentially do a little bit of initialization of the 2d array just so we can safely access things without getting arrays out of bound issues and then we're going to start iterating over um our array in order to spawning the actors so let's do that if you've ever done 2d arrays you'll be familiar with the pattern you just do like a for loop within a for loop but uh so the first thing we're gonna do is to initialize the values of zero so we can safely access the indexes in our 2d array so within my hex grid 2d array i'm just going to call a function called set num0 and this allows you to just initialize them as zero effectively um so first off we want to do our width we're going to set because you think we've got an array of an array so we want to go across all of our arrays and set them to zeros first and then what we want to do is we want to iterate over all of those newly or zeroed ones and we want to set each sub array sub array's value to be zero equal to the the grid height as well so let me write it it'll make a little more sense as i write it so we're just doing an uh a normal uh for loop here we're going to go over the the array.num because that we've just set here so this this 2d array didn't have a an amount of elements right until we did this this is the bit that says right you were going to have five things across and now what we need to do is say for each one of those five things you're gonna have five things down as well so that's all we're doing as much as it may look a little bit confusing okay so uh we'll do that and then i may have uh put an extra bracket in here that was my mistake okay uh and now what we do is we access the ith element of this and we're going to do the exact same code as we did above set num0 but this time instead of doing grid width we're going to do grid height so this allows us to be able to set different widths and heights and this is just going to create our kind of like empty structure for us okay after that that's the only bit that's a little bit weird if i'm honest with you in the in this staff if you're not used to doing a 2d array in in unreal so the next thing we want to do is to create the grid so we're going to go ahead and create this this loop it's going to be a to do at a loop within a loop so let's do our first one which is going to be very similar to what we wrote above but we're going to use more meaningful names here we're going to have our y first um we're going to set that as zero it's gonna go while y is less than our grid height and we wanna go ahead and do plus plus y you can do y plus plus if you want it it really doesn't matter i've just been uh it's enough to small optimization that i've kind of just been ingrained in me at the moment um and then we are going to go and do the exact same thing but this time we're going to do it with x and the grid uh width instead so let's just drop this in and go ahead and put x in put x in here and plus plus there we go and changes the grid width don't forget that okay good and let's set up the um braces for that as well now okay so this is effectively going to go through uh each uh each row first the inner part of this is going to be the thing that's iterating over first and then for each one of these rows uh it's then going to go uh through the columns so let's have a look what we need to calculate inside of here so uh first off we want to know if you if you remember earlier i referred to the fact that every odd row is kind of different here so we're going to do a little bit of calculation here to work out are we on our outro or not so um let's just call this odd row so are we on an odd row and that is going to be based on the y with which is the the kind of uh the going down direction right uh and you can just do a like a modulus 2 on this this is a quick way to know whether or not like the remainder of if you divide by two if it's one then you've got an odd number okay so this will just tell you are you on an odd row the next thing we're gonna do um is we need to work out if we are on an odd row then what is our kind of position going to be when we're spawning this new tile so if you think we're going if we had a five by five at the moment we're in position zero zero so we need to spawn in a tile there then when we go to zero one next or one zero um we then need to go ahead and spawn in a new tile there as well but the position needs to be shifted across so that's what we're calculating here so we can think about it as okay our exposition is going to be for the first row let's just do this first our first is going to be equal to whatever our x is at the moment right and then we want to times that by our offset that we were discussing earlier remember we were looking at the the tiles and saying how far across from one another they need to be so if you remember the difference between them was that that massive that weird one seven three dot whatever number right so we need to kind of uh write that in but we'll do it as a member instead right so we can tweak this and play around with it in editor so i am going to probably create something we'll call it a tile horizontal um offset let's call it this offset is the right word but we'll go with it for now so yeah let's go ahead and make this so it actually makes a little bit of sense should we so uh underneath these it's going to be kind of similar to these so let's just copy that in for now uh this is going to be based on the layout still so we can keep that first line up there but this is going to be a float this time instead and i called it i just accidentally deleted my uh my copy paste so let's go back copy this again and okay cool so we have our tile horizontal offset now we're also going to have um we want to do the vertical offset as well we'll we'll need that so we might as well copy this and do that while we're here so tile vertical offset okay um cool so now that we've got those so uh our exposition of where we're gonna spawn this is gonna be based on whatever iteration of x we're on time times by how far apart they need to be across then the next one um the next thing that we need to sort here is just setting up our y position then right so it'd be very similar we'll do const flow y pos and this is going to be equal to y times no surprises here at our vertical offset instead now the thing we haven't considered yet is um we need to consider the the slight offset that we have on every odd row do you remember this thing yeah how this is like half a tile with the cross yes okay so what we're going to go ahead and do we can uh we can add an extra membrane we could do the maths in here but for now i'm just going to expose it out as a member so we don't have to play around with code we can just tweak and edit it later so um yeah i'm going to go and toss it in here underneath this and we'll give it a slightly different name i guess we can call this our outro uh horizontal offset so odd row horizontal offset so this is what we need to add to the position each time that we're on an odd row just so it's shifted across by a little bit so the way you can think about this is we we can check hey uh is it an odd row if it is an odd row then we need to add the offset otherwise we don't right so you can write this out in a longer way i'm going to try and keep this concise i'm going to use a ternary operator which is kind of like an if statement in one line so we're going to say hey is this an odd row if it is an odd row then the value we're assigning to x is going to be uh equal to our this but we also want to add to it that new value we added right which is called our draw horizontal offset however if it's not an odd row then we just want this bit we just want the standard okay so that should give us our rules for offsetting it every second row bro so um now that we've got that we want to go on and spawn a class as well so we're going to have to if we want to spawn a class in unreal you need to know what kind of uh what class you're spawning and we're going to want to spawn one of our blueprint classes that we've made you know the grass hex tile that we made earlier and the water one now we can't refer to those in code because we made them in blueprint so we're going to do the t sub class of so that we can set that as a member variable and then it'll look in that variable and spawn whatever you've set up there so we're going to go ahead and create ourselves a t sub class of hex tile which will allow us to set the tile that we want to spawn in so again it's going to be another view property probably this isn't layout based this is more set up based so let's give it a more meaningful category here and then it's just going to be a t sub class of and then a hex tile is the the base class of those blueprints that we've made and i'm going to go ahead and call this grass hex tile for example okay a couple of things that we should think about we probably want to forward to clear what an a hex tile is in here so let's go ahead and do that because we're now we're using uh another class in this uh header so you can just go ahead and do that and then we'll fully include it in the cpp file when we use it okay so now that we've got that we can start going through our spawn logic so let's go ahead and do that so uh for now i'm just gonna go t subclass of um i'm gonna store it as a local variable for now it may look a bit redundant but we'll come back to add something later where it'll make a little bit more sense so we're just going to call this tile to spawn and for now we're just going to simply assign it to grass hex tile now um the the nice thing about this is like this is just a very basic implementation you could do whatever logic you want here to choose what type of tile to spawn so that's why i've got like a member for it so you can play around and experiment and think how you want to spawn different tars if you want but we're just going to spawn the grass one for now and then we're going to go ahead and actually spawn it so we want to we're going to make a new tile and we're going to do the normal that we need to do for spawning guitar so we want to spawn an actor uh that actor is going to be of a hex tile type and then the arguments we need to give it the that asset so it knows what type of class to spawn and then we we're going to give it a position so we're going to make an effector um now just making an f end point an f in point is quite a nice little it's just a wrapper for like a two values so i'm just going to go ahead and give this a x pause and a wide pause in here that i made earlier is that saying where to spawn it right based on these values that we calculated here um and then we want to do a f rotator and we're just gonna do a zero rotator we don't need to rotate it on a particular angle that we know of at the moment at least right so that should spawn it in for us and then um so i think it might be a good idea for us to probably add a uh give each tile an index as well so you know these f endpoints have talked about is like a little wrapper to say here's an x and a y value in one bit of in one member right so let's jump to this ahex tile and add one of those in i think that would be a good idea so um let's make this public so that we can access it as well you could make a center and get it for if you want but i'm just gonna be uh keep it simple for now so i'm going to make this a visible instance only so that we we're just going to use this just to show how it's working right so um this is going to be visual instance only um that should be fine actually i don't think we need to to do more than that we could give it a category still which is going to be equal to tile like the rest of them okay and this is going to be an f into point tile index so that's just the index that it is if it's in the top left corner it'll be zero zero uh and then it'll be one zero two zero three zero and then next line it'll be one z uh one zero one one one two etc so this is just representing where it is in that two-dimensional grid representation okay so now that we've got that we can access it uh we should set it because we know at this point while we're making it if you we've got the x and the y that we're iterating over right that is effectively the coordinates in this 2d grid so we're going to store it while we've got it now because that will be very useful for us later if we want to refer to a specific tile not by what actor is but by its tile index and that will really play into how we access our 2d array where we give it an x and a y kind of index in order to access something in our grid so okay let's do that so our new tile uh we want to go ahead and set the tile index to be equal to what we've we just set up a sec ago right which is going to be an f in point again uh which is going to be our x pause and our y pause okay so um actually no not the pause my mistake that would be a float we don't want to do that we want to just do our x and our y we want this to be 0 0 0 1 etc so x and y excellent okay cool so now that we've got done that the last thing to do is to assign it we spawned the array we now want to store that in our 2d array right so we're going to go x grid to d array and then we can access it via this nice system that i mentioned earlier we can now go x y um and on this first loop is going to be zero zero so the very first top left corner one we're going to store new tile in that position in our 2d array nice so this is the basics that we need here so we work out if we're on an odd row or not we work out the x position based on where we are looping over our grid height and our grid width which is our y and our x respectively um and then we choose what type of tile we want to spawn and then we spawn it and then we store in our 2d array that tile excellent okay so that should be sorted we may need to do some includes now so i'm going to right click and include my hextile that i made and that'll add it up to the top here uh i don't think we're using anything else that isn't uh part of the kind of base code like in point and rotator and that we don't need to include those so uh let's see if if that works then for us uh we'll do a hot reload and we'll see what happens hopefully we'll get there happy noise there we go right so now that that has been set up let's go and have a look at what we've got we go into our blueprints we need to create one for that hex grid manager that we've made now right so let's go ahead make a new blueprint class this is going to be from our grid manager that we've just been setting up we're going to call this bp grid manager or hex grid manager all right great and this is going to be like kind of an empty actor when we add it into the world so if i add it in uh we'll check it to zero zero okay so it's an empty active i'm not clicking on it we have this view here but we're not going to see anything in game to represent it other than the tiles that it's spawning but we haven't set it up yet if you remember we did go ahead and create a bunch of members for it right we need to set up these values and we didn't set any defaults for it so we're going to just set them up in editor now so let's go ahead and do that so let's go into the blueprint and here we go we've got our hex grid we've got our layout and we've got our setup so first off um we're going to set our asset if you remember this is the tiles that we want to spawn in it's a t sub class of hex tile so we're going to just point it towards our grass tile okay just so that it knows what the what is the asset to use for grass tiles and then we can think about the mass again so if you remember our grid width and our grid height is how many tiles in each direction do you want to go so let's do our width is five and let's do our height is four for example right so five cross four down now we need to put in our offsets uh and i know we've looked at this a few times before but just to remind ourselves so each tile across was that that funky number that we looked at through doing the square root of three times in by the size of our hex thing right so let's go in and set this now so we've got the calculator still open this was the let's just do it again square root of three oops wrong button excuse me so three like that times by 100 okay cool let's copy that in here and then uh um we have an odd row horizontal offset if we remember that was how far across does it need to be shifted on the second row and if we remember that was half of that value so we can now go uh times this value 5.5 to half it cool now we can copy that so we'll chuck that in as our how much to shift it across there we go and then our vertical offset if you remember was 75 of the height which was 150. okay so these values should roughly work for us and we're going to tweak them a little bit just because i think we we're getting some rounding errors probably you can see how it's stopped early here so it's not going to be perfectly accurate but it we can we can add little values to it it should be fine okay so um that is the set that we needed to do should we have a look what happens so uh we're in the middle of our map over here oh one thing i'd want to do actually is just as a good practice when you're adding in these actors that don't have a physical representation uh it's quite good you can add just like a billboard component maybe in just so it's easy to click on this thing and to see it in editor so let's just move this up in to the ear a little bit uh that should be fine so now what we should see is there's a little dinosaur head here yeah just so we can see it easy because you might have a few things that have this little white placeholder uh circle thing there so okay so there it is we're clicked on it and we can see now if we want to tweak those values more we can do that down here let's see what it looks like when we press play okay so this is the direction that we're facing let's let's make that let's fix that now actually so my you'll notice that my player start by default is facing in the x direction whereas if we're looking down at this map we kind of want to be looking so the y-axis is in front of us so i'm just gonna do two things i'm gonna well one thing actually i just need to rotate this player start so i'm just to press e to go into the rotate mode and then we're going to rotate it 90 degrees so that it's facing uh it's going along the y-axis now instead there we go so now when we press play i should be able to just look down and we're on that top tile and this is our grid you'll notice it is if i press um f8 to jump out this is our grid we've got five across and we've got four down just like we said we wanted right uh and what you can notice is remember i exposed this out to be visible only you can see the coordinate system in place so this is zero zero this is one zero this is two zero three zero et cetera and right at the bottom we're going to have our full three uh remember zero indexed uh like a razer right so there is five and uh five across and four down because there's zero index it all max at four and three respectively okay so that kind of works for us right and if we go into our top down perspective thing we can have a look and see how the gaps look and you do get these tiny little slivers and this is what i was on about earlier that um well there's two things you to to think about here one you might want to visually make it look a bit separate so they look more like tiles and two we have the rounding potential rounding issues as well so let's go ahead and tweak some of these values shall we like if you want you can you can always come into this view and just kind of move things around to see you know if you change this down to one for example you can move it around to kind of see well i want it to be like that much of a gap and work out how much you've moved it but um i'm just going to go ahead and just tweak some of the values we we have and this is why i wanted it to be edit anyway so i'll click on my manager and we've got these values before right so let's just uh go ahead and add some values i'm going to kind of simplify these these values actually no no we can just we can just add an offset to it so i'll add five to that i'm gonna add five to my vertical one and then the odd row offset if you remember that's like half the distance across so i'm just gonna add 0.25 which is half of five to that so that should give us oh hang on hmm not point two five uh two point five i wanted to do my mistake there okay so now what we should get if we look down is we get a little bit of a gap between them so that might look a little bit healthier when you're looking at your tiles on an angle you can see them all as tiles now for example now we're not going to talk about it go into detail now this is something for a future video or whatever but um if we're spawning in a lot of actors like this you do want to be a bit considerate of things like casting shadows you wouldn't want like a hundred of these tiles all to be cast in shadows so you can go into the meshes you can turn off things like casting shadows um you could even use mesh instancing to kind of increase increase uh performance with this stuff but that's beyond the scope of today's video so we're not gonna properly go into that but hopefully now you can see that we can change these values so if i now want like a 7x7 grid i can go in and press play and i've got myself a 7x7 grid this time which happens to be overlapping with the the set that we set over here so let's move that so it's a little less confusing for us there we go so that's handy we can now see um all of our tiles and it's giving us exactly what we set up and we can tweak that easily now without having to do the maths or move things around manually each time so that's positive now um we're going to do a couple of things just to help you debug as you if you want to take this further then um so at the moment uh i showed you that if we press f8 to kind of jump out of of our pawn we can then uh click on the different items uh the actors here and we can see that their tile index down here right let's go ahead and try and display this instead just so you don't have to jump out and click on them each time so there's two steps to this first we we're gonna just record that in the information about the tile index somewhere and then we're gonna make the tiles show that to us so first things first let's go ahead and um go into the bit where we're setting up the tile and what we're going to do in here is we're just going to do something called setting the actor label so by here should be fine if we go to new tile and we're going to go set actor label this is something that you can basically use for debugging the actor label is um and we're going to go ahead and make a string and we're going to just concatenate some stuff together so bear with me while i write this out and then it'll make a bit more sense to you so we want to give it a name of tile and then we're going to give it the x and the y coordinates afterwards so i'm doing the percentage d percentage d because we're going to they're basically going to get replaced by what we put next which is going to be our x and our y so what this is saying is for each tile as we spawn it give it a actor label of tile 0 0 tile one zero and the likes okay uh so that's what we need from a code side so let's go ahead and compile that and then we'll go into our uh base tile remember i said that's the idea of having a base tile is now i don't have to go into each of these tiles and and change the code i can just do it in the base one uh and we need to do a little bit of blueprint logic this isn't great for performance especially here but um we're going to go ahead and we can just uh tell it to print off or to display that so i think there is uh there should be a print oh no sorry debug string i think draw debug string i think that's the one there yeah so we can do that on tick for now just for example uh where do we want to spawn it we want to get the actor location so it spawns on the tile itself so get actor location will give us where we want to spawn it and then uh the value we want to give it is going to be based on this actor right so um you say get display name i think it is displaying or after label yeah that should do it ah okay i need to get a reference to this as well so let me get a reference to myself and then we want to get the display name and then we can just whack that into the text there so hopefully if we compile and save that what that should give us now is when we play this there we go we've got our index written out on top of the tiles you know it's a little bit messy but it gives you an idea it helps you work out if you're going to move on to look at how to do you know you might want to put units on this tile and move them uh and you want to give them a tile to move to or you're trying to work out the neighbors around each tile um it'll give you a better debug kind of visualization to help you with that uh and i would want to say on that point if you are looking to extend it i might do another video but um if not use this system there's plenty of information about how to work out you can look at like neighbors in here and it has a whole section on like how to work out the neighbors uh of um in in a hex based grid system so it's a really really useful uh resource that i pointed at you right at the start uh okay so uh we're at a point now where we've got some decent debug info the final thing i'll do since we made a water tile let's add in a water tile so you can start to see how you could build up on this instead of just having this that you can make it look a little bit more um you know varied and have different tiles in it and we're going to do a very simple i'll let it be on you to kind of come up with clever ways to do it for example with um in my game i ended up using like a 2d texture that you could paint different colors on and then it would spawn a different tile based on that uh you might want to do some random uh an algorithm which chooses tiles randomly based on certain conditions or neighboring tiles it's completely up to you but we're just gonna keep it super simple for now we're gonna go ahead and we're gonna um just do a little bit of logic to say hey sometimes spawn a water tile so we can just say hey um we need a water tab first off right we've got this grass hex tile we're gonna make a reference to an asset which is gonna represent our water hex tile so water hex tile so let's save that um we'll have to set this up in editor as well um but we'll assume that we'll remember to do that uh so if uh let's just do it we're just doing a little rolling the dice here basically so we do a random range of floats between zero and one uh and if that is greater than you could put in you might want to expose like a water chance so let's do like just for now let's let's do chants of water shall we like that um if it's more than if you say that hang on let me just make sure and put the right value 25 chance of water if it's more than it yeah so this would be less than it i guess would be more accurate that way if we put like 0.25 as our chance of water that means when you roll it you've got 25 percent chance of the water spawning yeah that's more correct uh less than or equal you might want to do as well okay so if uh our random roll is uh uh under the amount of uh water chance that we set up then we want to just change the tile to spawn to be equal to our water hex tile instead so it'll spawn a water tile in that environment very simple we're not doing anything complicated here but it's just to give an idea and give a starting point for people to start working on their own hex ideas then um so this chance of water which is going to expose out as a float value as well we'll just borrow this for now this can go into our setup and this can be our chance of water okay so um [Music] if we do a new hot reload now we should hopefully get a chance of water member variable that we can change and if we remember to set our water tile in our manager so we should do this on the on the blueprint of it so it's going to edit blueprint of this um where is the bit where we go to the hex here can you see our head water tile we want to go ahead and set about water tile there we've got a chance of water we can leave that as zero for now and that should mean that we don't get any water uh unless our random yeah this should all be green that's great yeah and then if we click on our grid manager and we say okay now we actually want to change this we want a 50 chance of water now let's do a little less let's do 25 chance of water now we press play we can see that we're getting water sometimes as well and that'll be different every time now because we're randomizing it right so the layout of water looks different and if we want to go ahead and make it mostly water we can go ahead and do that give it 90 chance 0.9 in there and there we go we've got tiny little bits of land instead little islands perhaps and you could sail around it's up to you what you want to do with uh these sort of games that's why i'm trying to leave this quite bare bones to allow people to kind of build on top of it however they want but um yeah that hopefully covers everything that i wanted to do now that you you now have a way to go ahead and set up a simple tile um and then we have done logic in the cpp so that um we can read the height and the width and then we'll loop over those and we will spawn a tile asset and we'll position it correctly based on the hex tile kind of system that you're going with and a final reminder that i do recommend uh using this this web page that i've been showing you throughout because it is super helpful and it allows you if you don't want to do it in the exact same setup as i did if you remember mine was um pointy like the pointy side up and then it shifts into the right on the second row if you want to do it different way with the flat side up on the top of it and you maybe want it to shift to the left on every odd row instead there's different maths and calculations that are explained on this page view so hopefully that'll be useful for you but yeah um if you enjoyed the video feel free to let me know if you want more about this so i can add show you more things you can do like how how can you work out the neighbors how can you add on units onto the grid and move them around how can you have a camera that you can pan around for example um i'm happy to do more content but for now i hope you've enjoyed i hope you've learned something i've been done you've been great and i'll see you again soon cheerio
Info
Channel: HonestDanGames
Views: 20,977
Rating: undefined out of 5
Keywords: game dev, honest dan, honest dan games, unreal, unreal engine, twitch, game development, games dev, games development, programming, c++, ue4, ue5, blueprint, learn, how to, tutorial, how to use unreal engine, ue4 help, what to do, first time, newbie, beginner, help, hex grid, hex, hex tile, hexagonal, 4x, tile map, tile grid, civ 6
Id: viw8QLV-lJ8
Channel Id: undefined
Length: 70min 19sec (4219 seconds)
Published: Sun Nov 07 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.