NavigationServer2D > region_set_navigation_polygon is slowing down and stuck UI of game

Godot Version

4.3 dev2
Executing on Macbook Pro m2 Pro 16gb


Well, when i call

NavigationServer2D.region_set_navigation_polygon(new_2d_region_rid, new_navigation_mesh)

where new_navigation_mesh is my NavigationPolygon, filled with data,
all UI of game stucks / slowing…

I tried a lot of things, but none of them make UI don’t get stuck.
Things like:
try execute this call in an separated Thread…
Try to call using call_defered()

Here an print of code, note that my var new_navigation_mesh: NavigationPolygon has filled with:
new_navigation_mesh.poligons_size = 40407
new_navigation_mesh.vertices_size = 161628

To make it clearer, if I comment out line 457 of the image the code will work perfectly, only missing the line NavigationServer2D.region_set_navigation_polygon() that was commented out. In this case, absolutely nothing will stop. Just uncomment line 457 and everything will stop.

Any tip for help?

Just way to big for a runtime navigation mesh.

When you set a new navigation mesh on a region the navigation map needs to rebuild with the new navigation mesh. The rebuild happens on the NavigationServer synchronization which happens on each physics process step. You can try disabling performance costly features like the edge connection margin but still, having >100.000 vertices and > 40.000 polygons is way to excessive for a single navigation mesh.

1 Like

I tried disable region_set_use_edge_connections with NavigationServer2D.region_set_use_edge_connections(new_2d_region_rid, false),

unfortunately, it did not solve the problem of freezing the UI/main thread process.
From my point of view, there are not that many points to process. It is a procedural map and this quantity represents only the tiles that can be traversed…

Is there any way to run the process, even if it is slow, WITHOUT LOCKING the UI?

Could NavigationServer2D not run in a separate process without taking over the entire main thread and only emitting a signal at the end?

As it stands, it seems to be impossible to create a loading/wait screen and, when the navmesh is finished loading, return to the game.

The entire UI simply freezes, it is not even possible to manipulate the window. The main thread was completely overloaded.

Should I open a bug to report the problem mentioned above?

Perhaps a signal is created and the main thread is no longer blocked.

It is not that simple as adding a signal.

The entire NavigationServer and all related nodes were designed years ago by some legacy contributors to be in full sync with physics process. There is nothing to be made async about physics, it is a stepped process.

Also the NavigationServer maps were designed to work with a single, large polygon soup for the pathfinding. Any change triggers a full rebuild of the polygon soup. There are no incremental updates. There is no automated partitioning or tiling. If you change a single edge you get a new map build in full.

All those things can not easily be added or changed when not designed from the ground up. Like just making the navigation map build run on a thread means every single server object needs to be remade to handle async iterations. All the navigation related SceneTree nodes need to be remade to handle async updates and queries. On top that breaks compatiblity for every existing project. We are basically talking about the work for a NavigationServer 2.0 for Godot 5.0 here.

Even if the navigation mesh would not freeze your game on the update, using an unpartitioned 40.000 polygon soup for pathfinding is not feasible for any game. Most game devs feel performance anxiety when they have to deal with a 1.000-2.000 unpartitioned polygon navmeshes and your navmesh exceeds that by a very large amount.

1 Like

Thanks for answering.
Assuming a tilemap of 200 tiles high x 200 wide.
Would the representation of a maximum of 40,000 tiles be too excessive for the navigation server? Would this happen in other game engines like Unity?
I was very disappointed to see the slowness and not having any way to deal with it (such as a loading screen).

I’m thinking about changing game engines, but I really like Godot, the only one I have fun with.

Would this limitation occur in a game engine like Unity? If this problem probably occurs there, I don’t think it would even be worth migrating the code to have the same result…

Do you know of any techniques for me to research and try to reduce/optimize this navmesh?
The problem is that it is a procedural map and each traversable tile is passed to navigationserver2d. In other words, water, rocks and other terrain elements do not make up the mesh, the rest of the tiles will be passed over and cause the UI to slow down and crash.

As we are talking about a map that on average is 200x200, there are 40 thousand square polygons and 120 million vertices (one for each end of the square)…

Am I making something wrong?
The idea is to build a base builder, so to make matters worse I will have to change the mesh when elements are built and block the path.

“Builder” games like that usually have their main pathfinding solution done with a grid navigation. The game may not look or feel like a grid game, but under the hood it uses a grid. The reason for that is because grids are predictable and very simple to update at runtime, requiring nearly no computation to change compared to rebuilding a mesh.

The reason why we still use navmeshes over grids in many other cases is because on a more static map a navmesh is superior as it can cover many, many grid cells with a single polygon. It also has an easier time to cover natural shapes, as they would require a high grid resolution with many cells.

If a Unity game still use a navmesh they use some way of partitioning, e.g. slice their game world into tiled update sections with only navmesh around the camera, everything else is just a simulated point graph so actors off-camera can still keep moving to a far away destination.

This means from your 200x200 game world only 8x8 might be actual navmesh or less, everything else off camera is simulated with an AStarGrid2D point graph.

Not a single “builder” game made with Unity, or Unreal for that matter, that I know uses their default navigation mesh implementation. That said those engines have the Detour TileMesh as part of their buildin solution so the basic tiling of navmesh is easier to do. Everything else that is required for a complete solution still needs to be largely done from scratch or with purchased plugins.

1 Like

You seem to be brute forcing, instead of optimizing - which will lead to exponentially worse performance depending on world size. Approach your world as unlimited - how would you handle a world with an endless amount of tiles?

1 Like

Thank you everyone for please answers.
There really are a lot of polygons to be processed. In my case, the ideal is for me to implement some polygon union algorithm to create a large polygon that represents a set of smaller polygons, thus reducing the number of polygons and optimizing performance.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.