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

[4.4.1] NavigationServer3D.map_force_update no longer synchronizing map #104671

Open
dougVanny opened this issue Mar 26, 2025 · 3 comments
Open

Comments

@dougVanny
Copy link

Tested versions

Not reproducible in: v4.3.stable.mono.official [77dcf97]
Reproducible in: v4.4.1.stable.mono.official [49a5bc7]

System information

Godot v4.4.1.stable.mono - Windows 10 (build 19045) - Single-window, 1 monitor - Vulkan (Forward+) - dedicated NVIDIA GeForce GTX 1060 6GB (NVIDIA; 32.0.15.6109) - Intel(R) Core(TM) i5-4690 CPU @ 3.50GHz (4 threads)

Issue description

After calling NavigationServer3D.map_force_update in a freshly created NavigationMap, it remains in an unsynchronized state, leading to subsequent calls failing

    NativeCalls.cs:7188 @ Godot.Vector3 Godot.NativeCalls.godot_icall_2_816(nint, nint, Godot.Rid, Godot.Vector3*): NavigationServer navigation map query failed because it was made before first map synchronization.
	NavigationServer 'map_changed' signal can be used to receive update notifications.
	NavigationServer 'map_get_iteration_id()' can be used to check if a map has finished its newest iteration.
  <C++ Source>  modules/navigation/nav_map.cpp:193 @ get_closest_point()
  <Stack Trace> NativeCalls.cs:7188 @ Godot.Vector3 Godot.NativeCalls.godot_icall_2_816(nint, nint, Godot.Rid, Godot.Vector3*)
                NavigationServer3D.cs:301 @ Godot.Vector3 Godot.NavigationServer3D.MapGetClosestPoint(Godot.Rid, Godot.Vector3)

Steps to reproduce

  • Create a new Navigation Map through NavigationServer3D.map_create
  • Setup that Navigation map with calls such as NavigationRegion3D.set_navigation_map
  • Call NavigationServer3D.map_force_update
  • Call NavigationServer3D.map_get_iteration_id and check if return is different from 0

Or, with the MRP, simply open and run the project

Minimal reproduction project (MRP)

✔️ PASS - Godot 4.3: navigationserver3d.mapforceupdate-bug 4.3.zip

FAIL - Godot 4.4.1: navigationserver3d.mapforceupdate-bug 4.4.zip

@dougVanny dougVanny changed the title NavigationServer3D.map_force_update no longer synchronizing map [Godot 4.4.1] NavigationServer3D.map_force_update no longer synchronizing map Mar 26, 2025
@dougVanny dougVanny changed the title [Godot 4.4.1] NavigationServer3D.map_force_update no longer synchronizing map [4.4.1] NavigationServer3D.map_force_update no longer synchronizing map Mar 26, 2025
@smix8
Copy link
Contributor

smix8 commented Mar 26, 2025

Godot 4.4 uses async map iterations by default which are threaded and sync on their own terms when the started map build is actually done.

In Godot 4.3 everything happened single-threaded as the only option so force updating map properties naturally caused the map graph to updated, usually followed by causing major performance problem due to the entire build running on the main thread.

The asyn map iterations can be toggled in the ProjectSettings or with the NavigationServer API.

@dougVanny
Copy link
Author

I see. Disabling it did help, and so does surround my map_force_update call like this

NavigationServer3D.map_set_use_async_iterations(map_rid, false);
NavigationServer3D.map_force_update(map_rid);
NavigationServer3D.map_set_use_async_iterations(map_rid, true);

I wonder what this change means for map_force_update though, as, to my understanding, it is only useful when you immediately need to have the map synced. Would it make sense to have map_force_update always work on a single thread or to maybe have that as an additional parameter?

It might be interesting to at least mention this on the Upgrading from Godot 4.3 to Godot 4.4 doc if there are no plans to change this behavior

@smix8
Copy link
Contributor

smix8 commented Mar 27, 2025

That function should just be deprecated and removed later as it is incompatible with async updates, enables mountains of project code smell that bites users at a later point in their projects, and had a big disclaimer from the very start when it was added for a reason.

To be clear, not removing that function anytime soon, likely not before Godot 5 because some projects clearly make use of it, but it cant be updated going forward.

It does not work outside of a full single-threaded context. When maps, regions, navmeshes and more all update async on their own a user cant force a map update and get the result that the user would expect. And then add threads to the mix and even more does not work anymore. There is no way to keep this function alive going forward. It does not help, users need to craft code that is robust enough that it can work with the normal (a)sync flow.

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

No branches or pull requests

2 participants