Godot TileMap chunking - is this impossible?

Godot Version



Hi all. I’ve been hitting a brick wall on this problem - I haven’t found any solution within Godot since the end of last year when I started working on this project, and I’m at my wits’ end.

To summarize, I’m making a chunking system for a procedurally generated overworld. The tiles are set on top of perlin noise values. The issue I’m facing is the performance of setting the tiles in chunks. I’m using set_cell_terrain_connect(), as my world is made up of various terrains. Here is the current state of loading chunks via this function:

As you can see, there is a bad stutter when using the terrain. The grass/sand is done via set_cell at the minute. I have tried splitting it up across frames as you can see, which is only 50 calls in a frame, and the frames will drop. Doing the same with the set_cell_terrain_connect function array is even worse:

Clearly, the main thread is being blocked. So what have I tried to do to mitigate this beyond the above? Firstly, I tried implementing threads. I realize that altering the scene tree on threads is not safe, so what I thought to do instead was to give every chunk IT’S OWN tilemap, and then do all the calculations, including the set_cell operations, on the tilemap which isn’t on the tree just yet. Then, I proceeded to call_defer the adding of the chunk to the scene_tree (as I also know that doing this on a thread is not safe). Here’s the result:

As you can, the offloading of the chunk to the thread works perfectly with no stuttering… until it crashes. The docs state that ‘Interacting with the active scene tree is NOT thread-safe.’, which I thought was fine, as I’m not interacting the with the active scene tree at all, I’m setting cells on something which wasn’t been added yet. However, the docs also mention that

Instancing nodes that render anything in 2D or 3D (such as Sprite) is not thread-safe by default. To make rendering thread-safe, set the Rendering > Driver > Thread Model project setting to Multi-Threaded.

This implies that this method shouldn’t be used either - even if it’s not affecting the scene tree from the thread. Setting the rendering Thread Model to Multi-Threaded made no difference either.

So what options are left? Is this a complete impasse as far as TileMaps are concerned? I’m reluctant to progress with the rest of my project at all, given the state of this basic feature that many published games include.

Any help would be greatly appreciated, as I do not want to drop this as it is a passion project and something I’ve wanted to do for a long time. Thank you in advance.

The docs state that ‘Interacting with the active scene tree is NOT thread-safe.’

Use ResourceLoader.load_threaded_request, which is thread safe. Don’t use the Thread class directly. You’re making it harder than is actually is. I even posted the complete core of a background loader you can use for this very purpose.

Look at my YouTube channel (https://www.youtube.com/@soapspangledgames2444) to see videos of it in action. The progress bar and notification text work smoothly because the chunk loading is done in the BackgroundLoader class I posted in other responses.

You’re going to have to restructure your code, but I’m leaving that as a programming exercise for you.

If you want to create endless/infinite world generation with tilemap + biomes + objects then you can watch my this video

Good video on the basics - but it doesn’t cover the complex issue of the stuttering caused by set_cell_terrain_connect and how it’s not possible to thread this at all

If I can’t use set_cell_terrain_connect on a thread of any kind then I simply can’t achieve what I’m trying to do