PROCEDURAL Terrain Generation (with Unloading) in Godot!

Поділитися
Вставка
  • Опубліковано 25 лип 2024
  • Easy and step by step tutorial on how to make procedural natural terrain generation in Godot 4+ (I used version 4.1 here). I also explain what each element does for beginners so you can customize it for yourself! Find the code in the link below!
    🌐Links:
    Code: github.com/kobeDevStuff/2D-Pr...
    Original tutorial: • Procedural Generation ...
    🎨 Check out the amazing artwork by Lily Zejlee: / lilyzejlee
    Connect with me on social media:
    Twitter - / kobedevstuff
    Instagram - / kobe.dev
    🎙️Help buy me a new mic!: buymeacoffee.com/kobedev
    Contact email: kobedevstuff@gmail.com
    Timestamps:
    00:00 Intro
    00:13 What is noise?
    00:46 Tutorial
    04:59 What does frequency mean?
    05:28 Back to the tutorial
    13:17 Chunk unloading
    17:24 End result
    17:40 Outro!
    #procedural #generation #godot
    game development,game dev,procedural,procedural generation,procedural generation 2d,procedural generation godot,godot,tutorial,godot 4.1,godot 4.2,easy,beginners,how to,how to make a procedural generated,procedural terrain generation, natural generation
  • Наука та технологія

КОМЕНТАРІ • 75

  • @JamesThomas-nr2og
    @JamesThomas-nr2og 6 місяців тому +7

    Hey man, thanks for this tutorial! It was super helpful! One issue I ran into is some major performance loss when moving far from the spawn/ origin, even with chunk unloading implemented. What I think was happening is that the cells in the unloaded chunks were still instantiated with an invisible/ uninteractable state. I fixed this by changing the .set_cell() method to .erase_cell(0, Vector2i(x,y)). This seems to fully remove the cells and allow chunks to properly unload.
    I will look into staggering the chunks being loaded and loaded also, as this seems to happen all within 1 frame causing slight stuttering.

    • @JamesThomas-nr2og
      @JamesThomas-nr2og 6 місяців тому +2

      Added a var time_since_chunk_loaded and var chunks_to_be_loaded = [ ] at the top of the script, then instead of drawing chunks immediately, they get appended to the chunks_to_be_loaded array. In _process, I added time_since_chunk_loaded += delta, and a conditional: "if chunks_to_be_loaded and time_since_chunk_loaded > 0.2: load_chunk(chunks_to_be_loaded[0]), chunks_to_be_loaded.erase(chunks_to_be_loaded[0]), time_since_chunk_loaded = 0"

    • @kobedev
      @kobedev  6 місяців тому +1

      Yeah at the time of recording I didn’t think of the fact that all the chunks are getting drawn and erased at once, having a queue would definitely help and I’m glad you found a solution, still not too sure if I’ll make another update video or not

    • @tannerroberts4140
      @tannerroberts4140 5 місяців тому

      @@kobedev Your idea is gold! I think a very successful follow-on to this would be adding the ability for the player to update the map (place/break a block like minecraft) and the saving of that tile state to memory.

    • @user-og6hl6lv7p
      @user-og6hl6lv7p Місяць тому

      It's probably also due to the fact that you're calling a square root function to calculate distance for every unloaded cell for *every* frame that passes. That is *massive* performance hit especially if you have hundreds or thousands of cells on screen. You could use godot's built in distance squared function or even create one using dot products e.g. Dot(v1, v1) * 4.0. This brings about a degree of inaccuracy, but you can always scale the distance value up/down so it reaches a better approximation.

  • @galacticgon925
    @galacticgon925 9 місяців тому +4

    Glad more and more people getting into GODOT and doing GODOT videos!
    I'm developing my game in GODOT.
    I would love to more and more on procedural generation and doing it in GODOT.
    Thanks for the video!

    • @kobedev
      @kobedev  9 місяців тому +2

      Thanks for the kind comment mate, I’m really happy you liked the video and you will definitely see more tutorials, devlogs, and informative videos from me soon!

  • @blarvinius
    @blarvinius 7 місяців тому +2

    Amazing! Perfect balance of design+code. More please!

    • @kobedev
      @kobedev  7 місяців тому

      Don't worry, after the next two videos from me I'll work on a tutorial!

  • @slothinahat
    @slothinahat 8 місяців тому +8

    YOO this is really good! I’m gonna have to take a look at that chunking code

    • @kobedev
      @kobedev  8 місяців тому +1

      Yeah I think I just need to implement a chunk deletion queuing system so they don’t delete all in one frame and cause jumps. I’m glad you enjoyed!

  • @MorseAmalgam
    @MorseAmalgam 8 місяців тому +3

    Really nice expansion on the original tutorial - More details about how particular things work, clearer audio, more easily readable text, new features. Improves on pretty much every facet of the information that was being conveyed in slothinahat's video.
    One thing I was surprised didn't make it into this is optimizations to reduce the amount of tiles being generated - With it being in the process function and having no checking, it's regenerating all the tiles in the space around the player every frame, when it only really needs to process them once.

    • @kobedev
      @kobedev  8 місяців тому +1

      Really good point mate! With all the kind feedback this video got and constructive ideas, I’ll definitely post a short upload fixing some issues especially making this feature and the chunk unloading more optimised

    • @MorseAmalgam
      @MorseAmalgam 8 місяців тому +2

      @@kobedev Very cool! Procgen stuff is the kinda project you could probably make a whole series out of adding new features and optimizations for :P Keep up the good work, these videos are well put together!

  • @greighlinv
    @greighlinv 8 місяців тому +2

    This looks awesome! I’d like to see you add certain entities for specific biomes like cactus can only spawn in the desert. Or flowers in the plains etc. I’m working on something completely different but this definitely helped my understanding of referencing the built in tile map functions 👍

    • @kobedev
      @kobedev  8 місяців тому +1

      Yeah absolutely you would just have to add another atlas and match that up to the moisture altitude and temperature levels of each tile, then run like a random number generator and only spawn that tile on top (you need to add another layer) if the random number = your predetermined number, set the range of random numbers between 1 and 10 if you want a 10% chance of that decoration tile appearing and you can adjust the range to make it more or less probable

  • @mercantilistic
    @mercantilistic 7 місяців тому

    Impressive tutorial, this is much better than many other tutorials I've seen lately.

    • @shanefoster5305
      @shanefoster5305 3 місяці тому

      He literally duplicated sloth in hat's tutorial that was done a year ago...

    • @mercantilistic
      @mercantilistic 3 місяці тому

      @@shanefoster5305 I'm not an archivist, I didn't watch all the possible videos on youtube. I don't even know who sloth in hat is.

    • @shanefoster5305
      @shanefoster5305 3 місяці тому

      @@mercantilistic just letting you know. Im not a fan of people duplicating other peoples content and posting it as their own taking credit for it. At least could have credited the guy…

  • @dausboot3997
    @dausboot3997 6 місяців тому +1

    Great stuff! Thanks for the help!

    • @kobedev
      @kobedev  6 місяців тому

      No worries!

  • @archwhynot
    @archwhynot 9 місяців тому +5

    Imagine if you tried recording this and then you realised you didn’t record the audio.
    That would be pretty goofy.
    Luckily that didn’t happen…
    Another great video KobeDev! 👍

    • @kobedev
      @kobedev  9 місяців тому +6

      You know what would be even goofier is if mid recording of the same video someone played earblasting metal pipe sound effect which was so jarring it made me jump and so loud it came through the microphone input.
      Luckily that didn’t happen…
      Another great comment ardy balls!

    • @archwhynot
      @archwhynot 9 місяців тому +2

      @@kobedev That would indeed be terrifying and it’s lucky it never occurred. If that happened to me, I’d hate the person who did that for the rest of my life. Who in their right mind would be that mean??
      Thankfully not me.
      Thanks KobeDev!

  • @greighlinv
    @greighlinv 8 місяців тому +2

    This is awesome dude very easy to follow. If i wanted to implement terrain sets so all the tiles connected smoothly with auto tiling how would I go about doing that. When I use set_cell_terrain_connect to place terrain sets it doesnt load and it throws out no errors

    • @kobedev
      @kobedev  8 місяців тому

      Yeah I was looking into the terrain method before hand briefly. To my knowledge you need a terrain set and I’m not sure how your project is set up so I can’t help you in this case but if you want to send me your project file and I can look into it just send it to my email in my about me or in the description and I’ll get back to you about that

  • @mincraft752
    @mincraft752 3 місяці тому +1

    Hey i love your videos u make everything so easy to understand . Can u please make a video about making your procedural terrain generation code optimized it gets very less frames and please make a save and load system so u can place and delete tiles.

    • @samuelhulme8347
      @samuelhulme8347 16 днів тому +1

      If Godot supports threads the terrain generation code should be placed in a a thread.

  • @remigouttefangeas
    @remigouttefangeas 5 місяців тому +1

    Hello, first of all thank you for this tutorial, it's exactly what I needed. I'm a beginner and I'd like to know if there's a way of preventing the player from spawn in the water, so limiting the appearance of water around the player during the first generation I imagine... ?

    • @kobedev
      @kobedev  5 місяців тому

      You could do that or do it the other way and position the player somewhere that has land terrain

  • @david18cruz1989
    @david18cruz1989 24 дні тому

    Interesting, if you go away from a chunk untill it unloads and then cvomes back, will it reload as it was or as a different chunck?

  • @EnumDev1
    @EnumDev1 9 місяців тому +2

    Thanks!!!!!!

    • @kobedev
      @kobedev  9 місяців тому +1

      No worries mate, it means a lot to me that this video was helpful and useful to you!

  • @starchsky
    @starchsky 5 місяців тому +1

    Without knowing much about what kind of compilation or optimization happens to the code/script in godot, there are some low hanging optimization that could be done. You should move and combine any math (especially divisions) out of the loop. You could predefine the "width/2" outside of the update. You could define the tile coordinates as out of the loop as you can (x outside of y loop, y before the noise lookup etc), instead of doing all the math again for each use inside the deepest loop. You could test using a dict/map for the loaded_chunks with coordinates as the key, so checking a value would be (hopefully) logn instead of n. And check the chunk before doing the noise lookup and cell setting, which might be unnecessary. Again, not sure what godot does with the script, but i assume there isn't much in the way of auto optimization happening.

  • @ArchaicVirusStudios
    @ArchaicVirusStudios 9 місяців тому +1

    This worked really well! I did notice however, there's quite a bit of lag once you get far enough from the origin to start unloading chunks. This causes a visual stutter due to the heavy operation of deleting a chunk within a single frame. Would you consider making a tutorial on deferring the chunk deletion to a threaded queue system? Then the chunk operations can be spread out over multiple frames, thus eliminating/reducing the stutter. I think this would make it a more viable system for practical use (no offense or anything). I have a similar worldgen system using noise, but I currently don't delete or unload chunks at all, and there is no lag or stutter, using a tilemap with 32x32 tile size @1920x1080, even after moving 500k+ tiles away, with 3 layers of tiles (fg tiles, bg tiles, and foliage). I guess Godot's tilemap system is very well optimized. Not to say that unloading isn't necessary, I just haven't coded up a system to handle it yet, which is what led me here :) Great tutorial! (And sorry if I sounded harsh, just trying to give constructive input)

    • @kobedev
      @kobedev  8 місяців тому +1

      Yeah i should have thought of that system it makes much more sense, but damn, Godot’s tilemap must be super optimised for it to have no latency for loading that many chunks, maybe chunk unloading in godot (2D at least) is pretty overkill, thanks for the feedback as I totally missed this one!

    • @ArchaicVirusStudios
      @ArchaicVirusStudios 8 місяців тому

      @kobedev Right!? I'm not sure if it sleeps the far away quadrants, or toggles visibility of them automatically. I assume the ladder, but I do know that the tilemap will batch the draw calls for tiles within whatever quadrant size is configured on the tilemap, but other then that I'm not totally sure what optimizations they use. Your system is really great though, and I will need to use it in my game (infinite universe Starbound-esque) Especially when leaving planets, as it doesn't make sense to keep them loaded after. Perhaps you could expand on this design in the future with the optimizations, but either way, this way very helpful, and thanks for your reply!

  • @viktormayer8923
    @viktormayer8923 Місяць тому

    how would you do to place objects in this world without it creating the object every time the process runs?

  • @fabioehrt1073
    @fabioehrt1073 6 місяців тому

    @KobeDev Hey, i have a short question i tried it and it seemed that it does not choose the from the fourth row (x,3). Since I´m a newbie im not sure were my mistake is. Im using Godot 4.2. I havent seen any tiles from the fourth row in the end of the video. Can somebody explain to me what i would have to change?

    • @kobedev
      @kobedev  6 місяців тому

      Could you send me your code either to my email or as a reply and I’ll try to see if your error is there, if not you can copy the project files in the link in the description which has the working code there, I haven’t tested it in godot 4.2 though

  • @jheartt
    @jheartt 6 місяців тому

    Is there a way to limit the overall size of the map, so it generates a shape and doesnt go on forever?

    • @kobedev
      @kobedev  6 місяців тому

      im not sure if this would work but you can try having 2 variables, maxwidth and maxheight and inside the function that draws the terrain just test first if the current position.x and position.y is inside this maxwidth and maxheight

  • @stupidrainbo
    @stupidrainbo 6 місяців тому

    Once I finish a series of Godot tutorials I'm going to try to make my own Valheim :D
    I know it's probably too ambitious, but I'm not afraid to scale things back and keep it simple, lol.
    Good tutorial! My mission would be to figure out how to do this with a heightmap for a plane mesh. I assume it would be a similar process but instead of using 2d tiles, it would literally be printing pixels onto a PNG file or something? I suppose I'll cross that bridge when I come to it xD

    • @kobedev
      @kobedev  6 місяців тому

      Yeah it’s a lot more complicated than printing pixels to a png file, my honest opinion is for you to make a few simple games first, platformer, top down, maybe a 3d, then you’ll have the tools and skills to try and approach your dreams without getting stuck at every point and not even knowing what to search up…. Trust me, I made the same mistake

    • @stupidrainbo
      @stupidrainbo 6 місяців тому

      @@kobedev Thanks for the advice! Right now I'm doing tutorials and making a few small games in them. Maybe I'll just try and temper myself though once I finish them xD

  • @ollie7597
    @ollie7597 8 місяців тому +1

    Please keep up! Thank you for the hard work, helpful and enjoyable.

    • @kobedev
      @kobedev  8 місяців тому

      Thanks man! I really appreciate the kind comment and I am definitely planning to make more videos like this!

  • @SirKill1000
    @SirKill1000 6 місяців тому +1

    Could you explain this loop?
    for chunk in loaded_chunks:
    var dist_to_player = dist(chunk, player_pos)
    1. Does GoDot just know the 'chunk' is a Vector2i because 'loaded_chunks' is?
    2. Is 'chunk' being looped through from 0 to the maximum value stored in the 'loaded_chunks' array?
    2a. If this IS the case, what happens if the player is at Vector2i(1,000,000, 1,000,000)? Will it cause major performance issues? (obv extreme case, but trying to understand)
    3. If the for loop is working the way I think it is, why not change the for x in range(width):
    for y in range(height):
    Into something like 'for pos in chunkRenderSizeVector2i:
    New to GDScript so I apologize if these answers are obvious.

    • @SirKill1000
      @SirKill1000 6 місяців тому +1

      Also subbed because this is a really great tutorial and this is the only part I wasn't able to understand, so thank you!

    • @kobedev
      @kobedev  6 місяців тому +1

      So loaded chunks is an array of the *positions* of tiles we have loaded in at the current time, looping through this (chunk, which is a Vector2i) we can calulate the distance to the player and if over the threshold it will no longer keep rendering that tile.
      to answer 2a and 2b consicely, no. a for loop will iterate through an arrays items, not the length of the list itself (in this case the items are the positions of tiles as mentioned above, which the iterator variable, chunk, refers to.
      to answer 3, the reason we dont do this is because you cant iterate a vector2i, so we need to do separate for loops that take care of the x and y components so we get all possible tiles.
      Thanks for the sub bro and I hope this helps mate!

    • @SirKill1000
      @SirKill1000 6 місяців тому

      @@kobedev Thanks for the clarification!

  • @user-dd8jn1fm8r
    @user-dd8jn1fm8r Місяць тому

    Instead of rounding Vector2, wouldn't it be better to use Vector2i?

    • @kobedev
      @kobedev  Місяць тому +1

      vector2i wont let us do some of the maths required and has some inconsistencies when you do this, plus the round function is not really that resource intensive

  • @ahmki52298
    @ahmki52298 3 місяці тому

    I cant even get it to let me use the tilemap after imported 😅

  • @mailmonkey
    @mailmonkey 5 місяців тому +2

    Is there any way to add collision shapes to the land?

    • @kobedev
      @kobedev  5 місяців тому +1

      There is! Click on your tilemap, go to physics layers and add a new layer, then go to tile set and select paint, then select from the property editor physics layer 0 and then start painting the hit box, if you are also using navigation you can do a similar thing with the navigation layers, with that, if you paint the whole thing it will count as a tile that the path finding will pathfind through, if not, it will act as a wall and the path finding will avoid it.
      Hope this helps!

    • @mailmonkey
      @mailmonkey 5 місяців тому

      @@kobedev Thanks

  • @DanTMZ
    @DanTMZ 9 місяців тому +12

    Wow it has 4 views and 5 likes which shows how elite this is

    • @kobedev
      @kobedev  9 місяців тому +1

      Someone must have used psychiatry or something

  • @QwertyDev24
    @QwertyDev24 9 місяців тому

    can you make a 3d version

    • @kobedev
      @kobedev  9 місяців тому

      I’m actually working on transferring my 2D project to 3D so I can pick up some knowledge, but I will definitely add that to the list! Great idea!

  • @MangleParty9
    @MangleParty9 9 місяців тому

    This is incredible

    • @kobedev
      @kobedev  9 місяців тому +1

      Yea it’s pretty impressive, you can take it further by adding shaders too, you can also make it hexagonal tiles or have an offset like brick effect and heaps more just with the TileMap node!

  • @Trupen2
    @Trupen2 9 місяців тому +3

    you are a bit too quite, especially when compared to that outro music, but overall great tutorial

    • @kobedev
      @kobedev  9 місяців тому +1

      I couldn’t turn up my audio any more than that unfortunately because of my goofy mic. Definitely will turn down the meme outro music so it isn’t too jarring and thank you for the kind comment and great feedback mate! 😊

  • @lilylee3990
    @lilylee3990 9 місяців тому +3

    🥵Kobe dev

    • @kobedev
      @kobedev  9 місяців тому +1

      Me too 🔥🔥🔥

  • @user-gd1qt1ce7q
    @user-gd1qt1ce7q Місяць тому

    Тяжело когда всего 4 гайда на ютубе по генерации в годо 3 из которых устаревшие а 1 англоязычный

  • @shanefoster5305
    @shanefoster5305 3 місяці тому

    This is literally a copy of "sloth in a hat" video a year ago...

    • @kobedev
      @kobedev  3 місяці тому +1

      I understand where you're coming from, I actually asked him directly before the video if it would be fine if i make this video and he said yes, additionally, I added unloading logic and some fixes that I saw was wrong in the first video