Okay now we are ready to implement the logic behind moving around and loading the additional chunks so additional part of our terrain when we move in a single direction for some time so for some distance moving from the first starting point to the next one so in our project in the game manager Script we are calling this method called world load additional chunk request when our conditions are met so when we have crossed the threshold after which after each distance we basically want to load more chunks so what we are going to do is we are going to open Our world script and if you are at the top you can simply select the drop down list here and search for load additional chunk request method and this method we are going to need to fill in in order to be able to load more chunks right now we are only debugging A message and since we have already refactored our get generate world method that now uses this get positions that player sees method that to get our data all they need to do is create another public void and this time we’re going to have this generate world a previous method takes in the Vector 3 in position and instead here we are going to call in this get positions that player sees this position and for our button we are going to have this generate world overload method that takes no argument and this we are going to call from our button click And we are going to call here generate world and we are going to simply pass here vector three and dot zero which we have passed previously insiders get positions that player sees so now we can assign this to our button but we can now use this which we can Call as a private method because we are going to only use it from inside of our world class we can call the same method inside our load additional chunk request so after we debug.log the statement we can pass here to this generate world a vector3 int dot round to End and we can round to hint our player dot transform.position so we need to pass here vector3 that’s why we need to round it to the integer the player position i don’t know quite why we have this empty method here but anyways what it will do it will Call the same method that we have used first to generate our world and since our get positions as player sees uses these select positions to create to only select the new chunks that we need to generate we are going to have here in this for each loop to generate only the additional chunks Not all of those five by five field of chunks instead we are going to only generate five chunks or i think at the corners when we are moving in the diagonal direction we could generate five and four so this would be i think nine chunks but basically this uh will still Freeze our unity for a bit until those chunks get generated and get uh gets instantiated so this is where we are going to introduce multi-threading in the next section but basically this is the idea now of course we would also want to delete the old chunks but for now Let’s test if our logic will work make sure that you save the script let’s go back to unity because as you might recall we have created the genetworld method and we need to assign it to our button so let’s go back to unity okay now inside our canvas we need to go to Our button and at the top at the bottom we should have this on click event which currently was oh i have closed this which it was calling this generate world method and it should still call it because we have recreated it and it is simply calling the next method And we can in addition to that simply select our button as a second callback and we can assign the function button and set it enabled or i think it should have something like interactive to be false so that we cannot really click it again because as you might recall we Have deleted the logic of deleting the old stuff before we generate the new stuff so we did not want to click it anymore okay so now if everything went all right let’s select the y axis on in the scene view so we can see the from the top what’s going on let’s click Play and we are going to select the regenerate button okay so now we are seeing our world from the top view and we have our player spawn in our game so let’s start moving in one direction and let’s take a look what’s going on as you can see the new Part of our world was generated and as you can see from the top view it matches perfectly our current terrain now one issue is that our previous chunks are not deleted or removed because we basically do not want to have them if we are moving in this direction we Did not care about them but let’s keep on moving let’s see if our terrain will be generated okay i have i think changed the direction of the movement and as you can see we can even see it in our game world that we are generating our new chunks Now if we get closer to our player as you can see we only have in our world two chunks generated so we have one two the middle one and one two on the other side so those should be the five chunks if we increase the size or the drawing distance of course It will take longer to generate those chunks so first of all i would like to stop uh keeping those old chunks since we did not simply need them and we can also lower the water level since this is pretty high let’s stop the game and just for the Sake of it let’s select the world and i think in the terrain generator in the biome generator we had the water layer and the water level hill here let’s set it to be something like three let’s see how it is generated right now and okay this is much better it is much Lower so we can safely traverse it and see a bit more great so now if we stop the game we need to deal with the issue of removing the old chunks when we move away from them so first thing we need to do is reopen our world script Okay and we want to find our generate method so generate world method that takes in the vector 3 in we can delete the old code that we had here because our new code works perfectly fine so now we have this new data generated and as you might recall this construct contains the Data chunk positions to remove and chunk data to remove but in our uh method called get positions that player sees we have never called those uh as you can see we have this uh set to be a new vector three int i will i think that we have this position update that We will not need anymore but for now let’s take care of creating those two lists so we will need to create two new lists so let’s copy the definition of a list vector3 int and we’re going to call this chunk data to remove and let’s create a second one and this will be Chunk positions to remove okay so for the first list we are going to call our world data helper and we are going to create a new method called get unneeded chunks and we are going to paste here arguments world data and all chunk positions needed so that we can calculate what remains And i have one too many semicolons and for the second method we are going to call world data helper get unneeded data and again we are going to pass world the data and all chunk data positions needed so here we have passed all chunk positions here all chunk data positions we can right Click on those methods and generate those in our world data helper and now we can right click on the first one and go to its definition great so this is an internal static list vector three into get unneeded chunks method created inside our world data helper And now what we are going to do is let me paste the code for this so what we are going to do here is we are going to have a list of vector 3 in positions to remove equals a new list of vector 3 int and we are going to look for Each position so var position in world data dot chunk dictionary dot keys so this is the dictionary of our chunks and those are the positions of our chunks that currently exist but we want to sort those or select only those so where position is so we are going to use lambda Expressions and where we allow us to select specific uh positions depending on the condition here and this is again from the link library and i think we had this imported at the top using system dot link okay so with this we can call well where position and pass The predicate so the condition basically all chunk positions needed so this is our list of the chunks needed contain position equals false so if our positions from the chunk dictionary are not inside our list of positions that are currently needed this means that those are the positions that we want to discard So if one of the data chunk position contains this position i think this is a redundant check but we i have added it for some reason we are going to add this to our new list positions to remove add positions and we are going to return these positions to remove list so let’s Now find our second method which was get unneeded data okay and this is this will be a bit different condition since previously we added this check which actually we could have put inside our aware clause as a second condition with the end now in this case in the get unneeded Data we’re going to return world data.chunkdatadictionary.keys so now we are looping through the chunk data dictionary again using the where method from the link library we are going to select positions and the predicate will be all data all chunk data positions needed what we have passed here as the second argument If this contains uh data is false so if we do not need this data and the second condition is very important for when we have modified our chunks so in case we have dug a hole or placed a block on the chunk data we have modified this And we cannot simply recreate it using our purlin noise or whatever noise system do we use to generate it basically we need to save this data and keep it stored in our dictionary now we could have a separate dictionary for it but basic idea is that If we want to save our data and load it we need to save and load those chunks that were modified and the rest we can recreate using our our procedural generation algorithm so the end condition world dot chunk data dictionary position dot modified by the player is equals false If this is not modified by the player then we can remove this data from our dictionary so basically we are getting the square positions so those are the positions that are unneeded and we need to convert them to list and we are returning the whole thing to our Method to our struct so this is how we are going to get the positions uh the data positions that are not needed anymore okay with those two methods done we can go back to our world script and we have those two filled in the Lists now all we need to do is pass them to our struct so chunk position to remove let’s pass it to our chunk positions to remove inside our world generation data and the chunks chunk data to remove let’s pass it to our chunk positions not to chunk position to Update i have made a mistake here we need to pass our chunk positions to remove our chunk positions to remove and chunk data to remove as the chunk data to remove and the chunk positions to update as new vector 3 in list okay and now this should be good so now we Have received the data about what we should destroy in our world so now like we can go back up inside our world script where we have generated our world okay so first we want to remove the old chunks that are not necessary basically we do not care in which or Which order we are going to do this but we need to do this anyways so we are going to look for each var position inside our world generation data.chunk positions to remove so this will be vector3 int okay you can create those by simply typing four and for each And tap tab to create this quickly and we are going to look for each position inside our world generation data dot chunk positions to remove and we are going to call our world data helper dot remove chunks and we’re going to pass this world and the position And the second loop will be var for each position which will be vector 3 in position in the world generation data dot chunk data to remove and we are going to call world data helper dot remove chunk data this time so this is the data And again we are going to pass that this so the world and the position and with those two methods we are going to simply do the logic behind removing those uh either the chunk game objects or the data from our dictionary so again let’s right click quick actions And generate both of those methods inside our world data helper and again we are going to click on the first one remove chunk right click and go to the definition okay so first of all what we are going to do is we are going to get the chunk render chunk Equals new null object and we are going to check if our world dot world data dot chunk dictionary uh has this value so we are going to call again try get value position out to the chunk value and we are going to pass here in case this is true world that remove Chunk chunk later on we are going to have a world renderer separate script that will deal with spawning and removing chunks that will also contain some object pulling to reuse those chunks but for now we are going to simply right click and quick action and generate this method inside our world And next we are going to have world world data chunk dictionary and we are going to remove this position from our dictionary and of course for our remove chunk data this will be a bit easier let me paste the code because all we need to do is call world world Data chunk data dictionary and we are going to remove this position from our dictionary now we need to call this additional method because our world data helper is a static class that is not a monobehaviour so we cannot really call from this destroy method to destroy our game object we need to Call this from a monobehaviour and our world is a monobehaviour so let’s right click on the remove chunk and go to this definition of this method and basically what we could do is simply call our chunk dot game object dot set active false since this will be cheaper than Destroying this and later on of course we are going to implement the object pooling and enquire it to a queue and we are going to reuse the old chunks when we are spawning our new chunks okay let’s save this actually select file and save all to save all the scripts And we should be good to go we are now removing the old chunks all the data and creating the new one okay so let’s go back to unity great if we press play now we should be able to see that if we regenerate our world our world is generally Generated let’s start moving in one direction let’s see if our world is working let’s actually let’s select our animated player so so that we can see it in the scene view and let’s keep on moving and as you can see our all the data and old chunks are now Gone as you can see those are disabled and only the new ones are visible so basically we save a lot of performance when we are disabling those old chunks and later on we can of course create a gizmo that will show us where are the world data positions that we Have currently available like i did in the end project but for now this is it now we can create our infinite world and as you can see there is some overhead of this as you can you can select the stats and you will see that our fps drops a Bit when we are loading we are performing all those operations and this isn’t terrible on a powerful machine but basically you can end up like this hitting a wall because it was never there before now one way to mitigate this would be to of course add our world more chunks so let’s select Four chunks for example okay so let’s press play and let’s see how it works we can reject our world but again the more chunks we have the more we will need to generate so the bigger hit the fps will get when we are moving and as you can see we are now not Hitting any walls when we are moving but basically what you can see is that our camera rotates after the update because we have missed couple of frames when we are removing our mouse so this is this teleportation effect where we are moving and if you are moving your camera It might end up somewhere in a strange place and as you can see we can still move on but this is a bit of an issue that we need to mitigate through a multi-threading algorithm in the next video we are going to implement the digging mechanic before we work on our additional biomes And later on about multi-threading on the multi-threading okay and this camera going through those walls is just a problem of the near clipping plane and far clipping plane you can play around with those values to stop the camera from going through the walls okay see you in the next video Video Information
This video, titled ‘Create MINECRAFT in Unity – S2 – P15 Creating infinite world’, was uploaded by Sunny Valley Studio on 2021-07-23 13:26:10. It has garnered 2392 views and 66 likes. The duration of the video is 00:19:23 or 1163 seconds.
In the Section 2 of this procedural voxel world generation Unity 2020 tutorial we will explore different procedural algorithms which uses Perlin noise to generate a nice looking landscape for our infinite voxel world.
Section 1 – Voxel Terrain Engine https://youtube.com/playlist?list=PLcRSafycjWFdYej0h_9sMD6rEUCpa7hDH
Section 2 – Procedural generation https://youtube.com/playlist?list=PLcRSafycjWFesScBq3JgHMNd9Tidvk9hE
Section 3 – Multithreading
Learn more from about Unity Game Dev in my video courses at: https://courses.sunnyvalleystudio.com/
Code files for everyone: https://www.subscribepage.com/voxel_world_tutorial_section_2
Project / code files for patreons: https://www.patreon.com/posts/voxel-world-end-53323870?utm_medium=clipboard_copy&utm_source=copy_to_clipboard&utm_campaign=postshare
Project / code files for YT members: Link in members only community post: https://www.youtube.com/c/SunnyValleyStudio/community
You can support me through Patreon: https://www.patreon.com/sunnyvalleystudio
Articles: Perlin noise – https://adrianb.io/2014/08/09/perlinnoise.html Domain Warping – http://www.nolithius.com/articles/world-generation/world-generation-techniques-domain-warping
Join the discord if you have any questions! https://discord.gg/RQEtYHz