From 505ace250d59a44d8b12d12d9e265d9c3d5647d2 Mon Sep 17 00:00:00 2001 From: Pawel Lampe Date: Sun, 3 Apr 2022 23:12:43 +0200 Subject: [PATCH] Add ability to `bake_navigation_mesh` off thread. This feature makes it possible to workaround problems such as: - long baking time due to heavy synchronization when parsing geometry from mesh instances - crash when freeing `NavigationMeshInstance` while baking - errors when actively baking node tree is being detached from the scene tree --- doc/classes/NavigationMeshInstance.xml | 3 ++- scene/3d/navigation_mesh_instance.cpp | 10 +++++++--- scene/3d/navigation_mesh_instance.h | 4 ++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/doc/classes/NavigationMeshInstance.xml b/doc/classes/NavigationMeshInstance.xml index cfb072d126b..e55e3b9d312 100644 --- a/doc/classes/NavigationMeshInstance.xml +++ b/doc/classes/NavigationMeshInstance.xml @@ -11,8 +11,9 @@ + - Bakes the [NavigationMesh]. The baking is done in a separate thread because navigation baking is not a cheap operation. This can be done at runtime. When it is completed, it automatically sets the new [NavigationMesh]. + Bakes the [NavigationMesh]. If [code]on_thread[/code] is set to [code]true[/code] (default), the baking is done on a separate thread. Baking on separate thread is useful because navigation baking is not a cheap operation. When it is completed, it automatically sets the new [NavigationMesh]. Please note that baking on separate thread may be very slow if geometry is parsed from meshes as async access to each mesh involves heavy synchronization. diff --git a/scene/3d/navigation_mesh_instance.cpp b/scene/3d/navigation_mesh_instance.cpp index 968e44e5f66..df27c51110e 100644 --- a/scene/3d/navigation_mesh_instance.cpp +++ b/scene/3d/navigation_mesh_instance.cpp @@ -172,13 +172,17 @@ void _bake_navigation_mesh(void *p_user_data) { } } -void NavigationMeshInstance::bake_navigation_mesh() { +void NavigationMeshInstance::bake_navigation_mesh(bool p_on_thread) { ERR_FAIL_COND_MSG(bake_thread.is_started(), "Navigation Mesh Bake thread is already baking a Navigation Mesh. Unable to start another bake request."); BakeThreadsArgs *args = memnew(BakeThreadsArgs); args->nav_region = this; - bake_thread.start(_bake_navigation_mesh, args); + if (p_on_thread) { + bake_thread.start(_bake_navigation_mesh, args); + } else { + _bake_navigation_mesh(args); + } } void NavigationMeshInstance::_bake_finished(Ref p_nav_mesh) { @@ -216,7 +220,7 @@ void NavigationMeshInstance::_bind_methods() { ClassDB::bind_method(D_METHOD("get_region_rid"), &NavigationMeshInstance::get_region_rid); - ClassDB::bind_method(D_METHOD("bake_navigation_mesh"), &NavigationMeshInstance::bake_navigation_mesh); + ClassDB::bind_method(D_METHOD("bake_navigation_mesh", "on_thread"), &NavigationMeshInstance::bake_navigation_mesh, DEFVAL(true)); ClassDB::bind_method(D_METHOD("_bake_finished", "nav_mesh"), &NavigationMeshInstance::_bake_finished); ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "navmesh", PROPERTY_HINT_RESOURCE_TYPE, "NavigationMesh"), "set_navigation_mesh", "get_navigation_mesh"); diff --git a/scene/3d/navigation_mesh_instance.h b/scene/3d/navigation_mesh_instance.h index ec49375aef9..5c274931d05 100644 --- a/scene/3d/navigation_mesh_instance.h +++ b/scene/3d/navigation_mesh_instance.h @@ -62,9 +62,9 @@ public: void set_navigation_mesh(const Ref &p_navmesh); Ref get_navigation_mesh() const; - /// Bakes the navigation mesh in a dedicated thread; once done, automatically + /// Bakes the navigation mesh; once done, automatically /// sets the new navigation mesh and emits a signal - void bake_navigation_mesh(); + void bake_navigation_mesh(bool p_on_thread); void _bake_finished(Ref p_nav_mesh); String get_configuration_warning() const;