Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the "Terrain" option for TilemapTileInfo causes horrible lag. #169

Open
cullumi opened this issue Sep 13, 2024 · 3 comments
Open

Using the "Terrain" option for TilemapTileInfo causes horrible lag. #169

cullumi opened this issue Sep 13, 2024 · 3 comments

Comments

@cullumi
Copy link
Contributor

cullumi commented Sep 13, 2024

This issue is likely due to the _set_terrain function inside of tile_map_gaea_renderer.gd.

Our set_cells_terrain_connect calls are updating the connections over an entire chunk's worth of tiles all at once. This likely has performance implications and should be spread out over time (for example, connecting only 3x3 groups of neighbors, then repeating in separate thread_safe calls over the entire chunk).

I plan to make a PR for this issue soon, just wanted to document my findings in the meantime.

@cullumi
Copy link
Contributor Author

cullumi commented Sep 14, 2024

Observations

After further investigation, the issue isn't as simple to address as I thought it would be:

  • Terrains as a feature may be too slow for large-scale procedural generation. For example, if you try to even just use the editor to place a sizable number of identical terrain tiles the entire engine freezes momentarily. Do too many and Godot thinks it's stopped working.
  • I'm noticing that the lag spikes correspond to a huge uptick in Physics Time in the editor. Perhaps these terrain changes are in some way batched into the physics update?

What's this mean for us?

A consequence of these two observations is that it seems like no amount of thread_safe calls made in the TilemapGaeaRenderer seem to make much difference in our lag problem-- perhaps because one expensive call is just immediately followed by another expensive call, which all lead to a big huge physics update of some sort.

Possible Solutions

We have some options for addressing these limitations:

  • Spreading these calls out in some way (like, minimizing the number per physics update or something like that).
  • Hiding Terrain-based generation behind a loading screen.
  • When splitting different Terrains up into multiple layers, it may actually be more performant to simply check for the boundaries and cook up our own solution (i.e. via Gaea's Modifiers). (Suggested Here)
  • Contribute to the Godot Engine to provide some lower-level ways to use Terrains in a more performant way? Could be fun lol

@GeminiSquishGames
Copy link

Maybe someone could help make a C# version for a larger scale, but usually making small chunks and only when you need them helps with GDScript performance-based generation, which probably would be better done at runtime rather than in the editor to generate things on the fly as the player is exploring. C# can be way faster for this type of procgen, either way, though it means your addon users would have to use the mono build of Godot. Unless you do a GDExtention in C++ then you have way more flexibility with performance and it should work with any build.

When you say thread safety doesn't seem to help, that says to me that it's doing it's job and preventing parallel processes from accessing the data that you may want to be doing in parallel for speed, maybe. Typically, I would toss the thread safety for the first pass for full-speed parallel calculations of chunks and then do my seam fixing and other clean-up in a second pass. Take this with a grain of salt as I have not familiarized myself with your code and am likely missing something.

@cullumi
Copy link
Contributor Author

cullumi commented Sep 27, 2024

When you say thread safety doesn't seem to help,

To clarify, the thread_safe calls I mentioned are being used to call non-thread-safe code in parts of the code that can optionally be run from a thread so as to not block the main thread (see How to optimize your generators). The functions called this way are almost exclusively built-in Godot engine methods for setting tiles and such (implemented in C++).

That being said...

Typically, I would toss the thread safety

I think you might be on to something here. I'm playing around with just forgoing the thread_safe call entirely (seeing as the bulk of the auto-tiling work is independently exclusive even when multiple chunks are loaded in parallel), and I'm seeing some promising results!

Maybe someone could help make a C# version for a larger scale

I get where you're coming from, but at the end of the day, this issue seems to be more of an implementation bottle-neck than a language bottle-neck.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants