HOW TO GODOT: Infinite procedural terrain generation

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so welcome to this tutorial on how to create an infinite procedural generator train so this tutorial will be a little bit longer than my previous ones because there's what goes into making this trail let's get started so first off we need to have some sort of first-person camera to move around in world so let's just create a quick first person camera so hit custom no let's use kinematic body rename it to player we give it a spatial node we rename this spatial to rotation helper and we add a camera as a child to that special node we give the player a script and we hit create okay so the fastest and easiest way is just to navigate yourself to this URL scroll down and copy this script here to get a first person script all right so we have to modify this a little bit first off we will remove the jumping we'll also remove the gravity for the player and we will make the camera to not be inverted by just multiplying online Edifier by negative one and the last thing we need to do is to declare these input variables as well let's go under project project settings input map okay so let's just hit move mount for word move mount backward movement left and movement right and just assign keys to this row we don't need collisions but we we can add it anyways and just create a capsule shape and just rotate it by 90 on the x-axis for now and we save this scene all right so we'll have to implement a chunk system in the game so for this to work we have to create a scene that represent each chunk in the game so we start off by creating a special or we rename this patient or to chunk and we can save it by pressing ctrl s and we attach a script to this chunk to this special note sorry and we can remove all the comments so I'll just increase this editor alright so first off we need to declare some variables we need a mesh instance to represent our terrain on the trunk and we need a noise we need an X variable in a set variable and we need a chunk size as well and we also need some sort of constructor that takes in some parameters and this is done using the init function it takes the noise X set and chunk size and that sets the variables as well we also need to give this a class name of chunk all right so each time we create a chunk we need to pass these parameters as to the constructor SMAP will be an open simplex noise that growth provides us the X and set value is where on the noise map that this chunk will retrieve its data and chunk style sharing site is just the size of chunk alright so we'll all right the ready function and we create a method called generate chunk okay so let's just give it some extra space you alright that is it for on how to generate a chunk servo regional tutorial this one so I won't go through the code here right but anyways that is it for a chance we can save this and we can minimize the script editor and we can close that as well alright so now I have to create a new special node we can rename it to world we can instantiate our player as well we can attach a script to the world we increase this editor again world has to have a reference to a noise map so will override the ready function I will set the noise to and new open simplex noise we're and we're just called random ice set the seed the random value we just set octaves impervious one to some values so these are the values as well that you modify depending on what you want trained to look like we will also have to declare some constants here so we also need a dictionary to keep track of all the chunks that we have in a game and we also need a another dictionary called unready chunks and you'll see later on why this one is used this is because we will deal with threads and also create a variable to represent the thread we can actually initialize this thread right over here all right first off we need to create a function to add a chunk to the game add chunk and we need to give this some parameters on where to add chunk and that is represented by the X and a set value so each chunk in the game will have a unique position so the key to the chunks where to the chunk dictionary will be represented by the position so let's just create the key this is done using the position that is divided by a comma so if chunks first we have to see if the chunks already exists in the in the dictionary has key we return we won't add anything okay else if not thread is active we had to start the thread okay load chunk and we'll have to pass some arguments to the method that we will be creating so we had to pass the thread left pasta X and a set value as well so now we have to set the unready charts with the key to let's say 1 and this is just so we won't create several threads that sets the same that creates chunks on the same position in the game over and over okay this is just because we are dealing with threats we have to do this so let's create this load chunk function that takes an array before I forget we need also we also need to check whether this key is in the Unrated chunks as well also has ok who returned ok so in the load chunk function we will retrieve the variables that we passed s array so first off we passed a thread and this is in the index 0 now then we have the value of x and it's on the index 1 and then we had a set value index 2 right when I will create the chunk and generate it so for chunk is equal to shunt dot dot new and as you remember we need to pass some parameters to the chunk so we'll pass the noise will pass X values will pass a set value and also pass the chunk size okay forget to multiply this or rather we could actually do it in the chunk hmm let me think about it doesn't matter we have to multiply it by chunk size as well you we set the translation to of the chunk nation to a new vector3 will set it to the X x chunk size see around the y axis and sad times chunk size as well all right so so when we had a chunk we first see we first check if we already if the chunk already exists in the in chunks or if it's in the unready chunks which means that it's going to exist because it's on another thread and being created right now and if it is if its existence either of these dictionaries will just return we won't have or anything else we will see if the thread is not active at the moment so it's not working on another chunk if it's not let's start a thread called a load chunk a function with these parameters and so this is just an array with different parameters with the different values in it and we set the unread a chunk with the giving key to one so in the low chunk we just retrieve all the variables in the thread and we generate the chunk and we set the chunks position and when we're done when with creating the chunk we call deferred load down so that is a function we will be creating and we pass in a chunk and a thread that's parameter so we'll create this one func load down with a chunk and thread as parameters okay so when all this logic has been I mean calculated we will then we will then add the chunk to to the scene and then we have to add the chunk to to the chunks dictionary as well so first off we need the key and we can retrieve the key from the chunks X and set position we just added and then we need to erase it from the Unrated chunks and then we need to wait for the thread to finish so this also makes sure's that thread is not active so when we have created a chunk and we have added it to the scene and everything we can go ahead and move on to the next chunk in the game alright so that is it for the adding of chunks in the game we need to create one more method get chunk by a given position and by the position we can also get the the key so first off we have to check if it exists in dictionaries of chunks that has K now if it has it and we return it else to just return note all right so we can save it as well so hit control s and save it so now for a process method method and this is where everything happens okay we'll create a function called update chunks will create a method function called clean clean up chunks also create a function called recept shelves all right so for up to chunks first we need to retrieve where the player is on in the world so that is done by player dot translation you so anyways we'll add the chunk and remember if the chunk already exists we'll just return it won't add an add anything okay what is wrong did I hmm yeah chunk amount okay oh sorry we should actually be able to try and run it now let's see if it's possible so we'll select the world and there it is okay so first off I want to head into the world and I want to increase the position of the Y position of the player and try again mm let's head into the player into the camera and just increased far by we max it out now okay so we went a little bit too high with the player so let's just lowered you know let's say also let's say that 200 okay and as you can see we get a terrain but we are not done here so let's get back to this world script and maximize this okay so as you can see we have two more mess-ups over here so when if you just leave it as it is for now as you can see when we move to play now okay let's just Inc as increased players move speed as well so in the players move script max speed is just times ten let's say touchdown okay so if you move the play now as you can see the terrain update and that's perfect no but but where we came from it should not be visible anymore okay because otherwise we will run out of memory pretty fast if you just keep on expanding the terrain so that we have to fix and it's pretty so this is not the perfect this is not a perfect system that I've created but it works so first off we need indeed we need to create a new variable in the chunk we will name it should remove it could be true as default actually so in the world scripts we need to first when we are doing all logic for chunks we will have to get the chunk get a chunk on position excess said and we have to check first if the chunk not equal no so it exists we set the chunk it should remove to false okay we set the chunks this should remove because it's within our vision and it should not be removed from the game so in the clean up chunks we will do some cleanup so 40-inch arts will iterate through each each chunk in the chunks dictionary and we get it retrieve it from the chunks by the key and if a chunk should remove remove it it's a chunk not q3 and we also need to erase it from the dictionary so and this just means that if this variable is true then it should be removed and all chunks that are not that is not in our vision of the player or within this for loop should be true and this is what this function is for so for K in chunks jokes he should remove equals true all right so let's just try it out to see if it's worth if it works so we generate the first square and then we move a little bit and we see the chunks update and they also get removed from where we came from and this is awesome okay so just to make the terrain look a little bit nicer in our world let's just create a temporary machine stance and just give it a special material and hit this little arrow here and convert to shader material and we save this one as well save as terrain not material okay we can remove this machine instance yeah so the terrain material now contains all the properties that that a special material does first we need to create two uniform variables to represent our sand color and our grass color we also need to create a very flat out color create a function called love color and we just set out color based on the Y position and we lurk between the two colors that is represented from the sand color on the grass color so I think there you have it okay so we create two uniform variables we create out color we create a function that lurks between two colors and we set out color to and we calculate out color based on Y position of the vertex so once again this is something that I've already talked about in my previous tutorial on how to create a random generated terrain so if you're interested go check it out I won't explain anything further on this one just one last thing is to change the albedo over to out color and that is it in the chunks the chunks in we head over to the script and we just attached material to this one so plain mesh material equals let's zoom in a little bit so you can see very much material equals load terrain material BAM and we preload this as well right so let's save and hit run and see if it works and as you can see we get a nice awesome cool looking terrain there is so now we have some sand and some grass on it final touch we can just we can create some a phone call generate water and we create a simple simple water can I actually just create a plain mesh we don't even able to subdivide it we do need to create a material for the water so let's do that right click on the res folder hit new resources special material create a new one oh we do not know where that one that we set it we save it as where and in the albedo sorry first in the flags we set transparent to true and in the albedo we change the color to a bluish color and we lower the Alpha Channel a little bit something like that and we then set it to water Dartmouth aerial add this to display mesh as well okay so I think that is all we have to do we can try it out and see it works it do not work it do not work why doesn't it work oh sorry we need to play the mesh instance mesh instance with mesh mesh instead new mesh instance that mesh equals Lane mesh and then we just set it we add mesh instance that's a child and now we have some simple water as well alright so that is it guys peace out
Info
Channel: codat
Views: 29,561
Rating: 4.9080458 out of 5
Keywords: terrain, godot, godot 3.1, terrain generation, random, random terrain, godot engine, tutorial, how to
Id: rWeQ30h25Yg
Channel Id: undefined
Length: 29min 55sec (1795 seconds)
Published: Sat Jun 22 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.