Procedural Landmass Generation (E07: Endless terrain)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone welcome to episode 7 so over the next few episodes we're going to be implementing this endless terrain system the basic idea being that we only spawn in the chunks of the terrain which are visible to the player and then as soon as there are no longer visible to the player we hide them and we also sort of dynamically change the level of detail based on how far away they are from the player for this episode we'll just be getting the basics of the system in place so that is the spawning and hiding of the chunks ok so to get started let's create a new C shop script called endless terrain or infinite terrain something to that effect and we want to create a couple of variables so to start with a public constant float just for how far the viewer can see so I'll call this the max view distance so that equal to something like 300 the constant keyword in case you're not familiar with that is just guaranteeing that this value can't change at runtime next let's get a reference to our viewers transform so that we'll be able to figure out their position so let me make a public static vector 2 here for the viewer position I'm just making a static so that we can easily access it from other classes later on next we want an int for the chunk size as well as an int 4 based on the chunk size and the max view distance how many chunks are visible so we can just call this the chunks visible in view distance all right so then let's make a start method and we want to fetch the chunk size from the map generator this is stored as a constant int map chunk size it's going to make this public so that we can access it one potentially confusing thing about this map chunk size integer and why should probably figure out a better name for it is that it has a value of 241 but as we discussed in the previous episode the dimensions of the actual mesh that we generate we'll be one less than that so our mesh is 240 by 240 so in the endless terrain we're going to want to say that our chunk size is actually map generator dot a map chunk size minus 1 and then make sense that the number of chunks visible in the view distance is just equal to how many times we can divide the chunk size into the view distance so we can say that's equal to max' view distance divided by chunk size and this is expected to be an integer so we'll just round that to the nearest integer with math F dot around 2 inch so let's imagine we've divided our game world up into a grid with each of the blocks being 240 by 240 so a single terrain chunk fits into a single block if we place the viewer somewhere onto this grid then what the chunks visible in view distance variable is determining is quite simply the number of terrain chunks around the viewer that will instantiate now just to be clear for when we're programming this in a minute when I talk about the position of a terrain junk I'm referring to its center as it would be in the game world so if we make this 0 0 then the choong-soo its left would be negative 240 0 and to its bottom right would have 240 and negative 240 when I refer to its coordinate however I mean its position divided by the chunk size so on the left would have negative 1 0 on the right 1 0 and on the bottom right 1 negative 1 and so on so with that said let's create a method called update visible chunks and what I want to do first of all is to get the coordinate of the chunk that the viewer is standing on so we can say int current chunk chord X will be equal to math F I want to run this to the nearest integer of viewer X sorry there should be a viewer position dot X divided by the chunk size and then the same story for current chunk chord why leave your position Y divided by chunk size and then we'll want to loop through all of the surrounding chunks so we'll say four-inch Y offset starting at negative chunks visible in view distance going all the way to Y offset less than or equal to positive chunks visible in view distance and then obviously just incrementing by one each time we want to do the same thing for the X offset we can then say vector to viewed chunk code is equal to a new vector 2 with the x value equal to the current chunk code X plus the X offset and the Y value equal to current chunk old Y plus the Y offset now if you only want to instantiate a new terrain chunk at this coordinate if we haven't created one there already so we're going to want to maintain a dictionary of all of the coordinates and terrain chunks so that we can prevent duplicates before we do this though let's let's quickly create a public class to represent our terrain chunk object and then we won't worry about what goes in there yes but if we say using system collections generics you get our hands on the dictionary we can say dictionary with a key of vector 2 for the coordinate and then the corresponding terrain chunk as the value and just call this our terrain chunk dictionary and set it equal to a new dictionary so now back in the update visible chunks method we can say if the terrain chunk dictionary contains the key view chunk award then we're going to reduce some stuff in here later on but if it doesn't contain that key then we'll want to instantiate a new terrain chunk so we can just say terrain chunk dictionary a dot as we give it the key which is the view chunk award and then we can say new terrain chunk all right so let's now pay some attention to our terrain Jean class so one of the things we wanted to do for the moment is to instantiate a plane just to use as a sort of visual placeholder until we implement this with the map generator so let's create a constructor public to ring chunk and this can take in a vector two for the coordinate as well as an integer for the size and outside here we can just keep a vector two position and we can say that the position is equal simply to the coordinate multiplied by the size and since we're going to want to position this in 3d space let's also create a vector three just call this position V 3 is equal to a new vector3 with an X of position X Y of 0 and a Z of position dropped Y ok then we want to instantiate a plane object so let's just keep a reference out here game object mesh object and we can say mesh object is equal to game object great primitive and we want to create a primitive of type plane and then we can say mesh object dot transform a dot position is equal to our vector three version of the position and we also want to set its scale so mesh object transform dot local scale is equal to vector three dot 1 multiplied by the size and since the primitive plane mesh is actually ten units in its default state we can just divide this by 10 to give it the correct scale okay so we're also going to want a public method so that we can tell the terrain chunk to update itself and what I mean by updating itself is it's going to find the point on its perimeter that is the closest to the viewers position and it will find the distance between that point in the viewer and if that distance is less than the maximum view distance then it will make sure that the mesh object is enabled and if that distance exceeds the maximum view distance then it will disable the mesh object so in order to find the point on the parameter that is closest to another point we can use the bounds struct so let's create a bounds called bounds and up here we can say bounds is equal to a new bounds and we'll pass in our position and we also need a vector two for the size so vector 2.1 x size okay so bounds has a very convenient method called square distance which returns the smallest square distance between the given point and this bounding box so we'll want to pass in our viewer position and we can say that float viewer dist from nearest edge is equal to that except we don't want it to be squared so we'll get the square root of the square distance all right and we can say that whether or not this chunk is visible is determined by the viewer distance from edge being less than or equal to the maximum view distance okay so we're going to want to create a another method just a public for ade setvisible which will depend on blue visible so we can just set the active state of the mesh object to visible all right and then of course from update we're going to want to say set visible and pass in our visible bool then in the in the cone structure I'm just going to say set visible false so that the sort of default state of the terrain chunk is invisible and then we let the update method determine whether it should then become visible okay so up here we're going to have to add some arguments in for the constructor so let's pass in the view chunk coordinate as well as the chunk size and then in this if statement over here where we've said if we've already generated a tauren chunk for this coordinate then we're going to want to update that current chunk so we can say terrain chand dictionary pass in our key and call update it should probably actually be best if I rename this from update to something like update terrain chunk just so that we never got confused thinking that that was the update method that gets called by unity automatically and we recruit one of those right now each frame will want to update the viewer position very and say view position dot or other your position equals new vector2 pass in viewer position X and viewer dot position dot Z and then also want to just update the visible chunks okay so let's head over into unity and let's add our endless drawing script onto the map generator object can create a little cube call the solve viewer and assign that to the viewer transform I'm also just going to hide the mesh so it doesn't get in our way and let's press play so the game window is interfering let's just put it in the corner and try this again so we're getting all of these planes generating around the viewer object which is nice but they are not disabling themselves as the viewer moves out of range so the reason for this is since we're only updating the chunks which are within this offset any chunks that were visible the previous frame but which have since moved outside of the offset won't be updated so we're going to create a list of terrain chunks and we'll call this terrain chunks visible last update all right and then before we update the newly visible chunks we're just going to go through all of the chunks that were visible last update and we're going to set them to be invisible so let's say 4 into I equals 0 I less than terrain chunks visible last update count I plus plus and we can say current chunks visible last update I set visible false having done this we'll want to clear the list so we can say chunks visible last update clear and then we'll want to add any terrain chunk that is visible this frame to that list so we'll just need a little method in the terrain chunk class to find out if the mesh is visible so let's create public pool is visible and it's just returns mesh object dot active self alright so if this terrain chunk is visible then we'll want to add it to the terrain chunks visible last update list so dot add terrain chunk Dictionary and the coordinate all right so let's quickly try this again now and you can see that the planes are updating correctly it's a little bit irritating having them having them all appear in the hierarchy here at much prefer if they just parented themselves to the map generator so let's add in a a transform parameter to the terrain trunk a constructor called parent and then we can just say mesh object transform dot parent is equal to parent and then when we create the new terrain chunk we can just pass pass in this transform let's also try this out with a new max view distance say 450 save and hit play again so everything's working very nicely admittedly the result of this episode is not exactly overwhelmingly exciting but do the necessary step 2 episode 8 where things will begin washing up as we integrate this with the map generator and introduce threading and whatnot so until then Cheers
Info
Channel: Sebastian Lague
Views: 162,572
Rating: 4.9758091 out of 5
Keywords: procedural generation, proc gen, perlin noise, world, procedural, terrain, random, Unity (Software), Unity 5
Id: xlSkYjiE-Ck
Channel Id: undefined
Length: 17min 24sec (1044 seconds)
Published: Mon Mar 14 2016
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.