diff --git a/doc/classes/Navigation2DServer.xml b/doc/classes/Navigation2DServer.xml index 8b579923e..5e9c65cab 100644 --- a/doc/classes/Navigation2DServer.xml +++ b/doc/classes/Navigation2DServer.xml @@ -495,6 +495,13 @@ Creates a new navigation obstacle. + + + + + Returns [code]true[/code] if the provided [param obstacle] has avoidance enabled. + + @@ -509,11 +516,20 @@ Returns [code]true[/code] if the specified [param obstacle] is paused. + + + + + + If [param enabled] the provided [param obstacle] affects avoidance using agents. + + + Set the obstacles's [code]avoidance_layers[/code] bitmask. @@ -540,6 +556,22 @@ Sets the position of the obstacle in world space. + + + + + + Sets the radius of the dynamic obstacle. + + + + + + + + Sets [param velocity] of the dynamic [param obstacle]. Allows other agents to better predict the movement of the dynamic obstacle. Only works in combination with the radius of the obstacle. + + diff --git a/doc/classes/NavigationObstacle.xml b/doc/classes/NavigationObstacle.xml index a8f5f9edf..73f987f54 100644 --- a/doc/classes/NavigationObstacle.xml +++ b/doc/classes/NavigationObstacle.xml @@ -12,12 +12,6 @@ - - - - Returns the [RID] of this agent on the [NavigationServer3D]. This [RID] is used for the moving avoidance "obstacle" component (using a fake avoidance agent) which size is defined by [member radius] and velocity set by using [member velocity]. - - @@ -37,10 +31,10 @@ Returns the [RID] of the navigation map for this NavigationObstacle node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract obstacle on the NavigationServer. If the obstacle map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle and also update the obstacle on the NavigationServer. - + - Returns the [RID] of this obstacle on the [NavigationServer3D]. This [RID] is used for the static avoidance obstacle component which shape is defined by [member vertices]. + Returns the [RID] of this obstacle on the [NavigationServer3D]. @@ -67,6 +61,9 @@ + + If [code]true[/code] the obstacle affects avoidance using agents. + A bitfield determining the avoidance layers for this obstacle. Agent's with a matching bit on the their avoidance mask will avoid this obstacle. diff --git a/doc/classes/NavigationObstacle2D.xml b/doc/classes/NavigationObstacle2D.xml index 1e7688f8e..2dbfa5f46 100644 --- a/doc/classes/NavigationObstacle2D.xml +++ b/doc/classes/NavigationObstacle2D.xml @@ -12,12 +12,6 @@ - - - - Returns the [RID] of this agent on the [NavigationServer2D]. This [RID] is used for the moving avoidance "obstacle" component (using a fake avoidance agent) which size is defined by [member radius] and velocity set by using [member velocity]. - - @@ -37,10 +31,10 @@ Returns the [RID] of the navigation map for this NavigationObstacle2D node. This function returns always the map set on the NavigationObstacle node and not the map of the abstract obstacle on the NavigationServer. If the obstacle map is changed directly with the NavigationServer API the NavigationObstacle node will not be aware of the map change. Use [method set_navigation_map] to change the navigation map for the NavigationObstacle2D and also update the obstacle on the [NavigationServer2D]. - + - Returns the [RID] of this obstacle on the [NavigationServer2D]. This [RID] is used for the static avoidance obstacle component which shape is defined by [member vertices]. + Returns the [RID] of this obstacle on the [NavigationServer2D]. @@ -67,6 +61,9 @@ + + If [code]true[/code] the obstacle affects avoidance using agents. + A bitfield determining the avoidance layers for this obstacle. Agent's with a matching bit on the their avoidance mask will avoid this obstacle. diff --git a/doc/classes/NavigationServer.xml b/doc/classes/NavigationServer.xml index 05250d8f4..0056cf3bd 100644 --- a/doc/classes/NavigationServer.xml +++ b/doc/classes/NavigationServer.xml @@ -559,6 +559,13 @@ Creates a new obstacle. + + + + + Returns [code]true[/code] if the provided [param obstacle] has avoidance enabled. + + @@ -573,6 +580,21 @@ Returns [code]true[/code] if the specified [param obstacle] is paused. + + + + + Returns [code]true[/code] if the provided [param obstacle] uses avoidance in 3D space Vector3(x,y,z) instead of horizontal 2D Vector2(x,y) / Vector3(x,0.0,z). + + + + + + + + If [param enabled] the provided [param obstacle] affects avoidance using agents. + + @@ -613,6 +635,30 @@ Updates the [param position] in world space for the [param obstacle]. + + + + + + Sets the radius of the dynamic obstacle. + + + + + + + + Sets if the [param obstacle] uses the 2D avoidance or the 3D avoidance while avoidance is enabled. + + + + + + + + Sets [param velocity] of the dynamic [param obstacle]. Allows other agents to better predict the movement of the dynamic obstacle. Only works in combination with the radius of the obstacle. + + diff --git a/modules/navigation/nav_obstacle.cpp b/modules/navigation/nav_obstacle.cpp index e69d7697f..a0a6f158b 100644 --- a/modules/navigation/nav_obstacle.cpp +++ b/modules/navigation/nav_obstacle.cpp @@ -30,11 +30,16 @@ #include "nav_obstacle.h" +#include "nav_agent.h" #include "nav_map.h" NavObstacle::NavObstacle() { + agent = nullptr; map = nullptr; + radius = 0.0; height = 0.0; + avoidance_enabled = false; + use_3d_avoidance = false; avoidance_layers = 1; obstacle_dirty = true; map_update_id = 0; @@ -43,24 +48,104 @@ NavObstacle::NavObstacle() { NavObstacle::~NavObstacle() {} +void NavObstacle::set_agent(NavAgent *p_agent) { + if (agent == p_agent) { + return; + } + + agent = p_agent; + + internal_update_agent(); +} + +void NavObstacle::set_avoidance_enabled(bool p_enabled) { + if (avoidance_enabled == p_enabled) { + return; + } + + avoidance_enabled = p_enabled; + obstacle_dirty = true; + + internal_update_agent(); +} + +void NavObstacle::set_use_3d_avoidance(bool p_enabled) { + if (use_3d_avoidance == p_enabled) { + return; + } + + use_3d_avoidance = p_enabled; + obstacle_dirty = true; + + if (agent) { + agent->set_use_3d_avoidance(use_3d_avoidance); + } +} + void NavObstacle::set_map(NavMap *p_map) { - if (map != p_map) { - map = p_map; - obstacle_dirty = true; + if (map == p_map) { + return; + } + + if (map) { + map->remove_obstacle(this); + if (agent) { + agent->set_map(nullptr); + } + } + + map = p_map; + obstacle_dirty = true; + + if (map) { + map->add_obstacle(this); + internal_update_agent(); } } void NavObstacle::set_position(const Vector3 p_position) { - if (position != p_position) { - position = p_position; - obstacle_dirty = true; + if (position == p_position) { + return; + } + + position = p_position; + obstacle_dirty = true; + + if (agent) { + agent->set_position(position); + } +} + +void NavObstacle::set_radius(real_t p_radius) { + if (radius == p_radius) { + return; + } + + radius = p_radius; + + if (agent) { + agent->set_radius(radius); } } void NavObstacle::set_height(const real_t p_height) { - if (height != p_height) { - height = p_height; - obstacle_dirty = true; + if (height == p_height) { + return; + } + + height = p_height; + obstacle_dirty = true; + + if (agent) { + agent->set_height(height); + } +} + +void NavObstacle::set_velocity(const Vector3 p_velocity) { + velocity = p_velocity; + + if (agent) { + agent->set_velocity(velocity); } } @@ -80,8 +165,16 @@ bool NavObstacle::is_map_changed() { } void NavObstacle::set_avoidance_layers(uint32_t p_layers) { + if (avoidance_layers == p_layers) { + return; + } + avoidance_layers = p_layers; obstacle_dirty = true; + + if (agent) { + agent->set_avoidance_layers(avoidance_layers); + } } bool NavObstacle::check_dirty() { @@ -90,6 +183,26 @@ bool NavObstacle::check_dirty() { return was_dirty; } +void NavObstacle::internal_update_agent() { + if (agent) { + agent->set_neighbor_distance(0.0); + agent->set_max_neighbors(0.0); + agent->set_time_horizon_agents(0.0); + agent->set_time_horizon_obstacles(0.0); + agent->set_avoidance_mask(0.0); + agent->set_neighbor_distance(0.0); + agent->set_avoidance_priority(1.0); + agent->set_map(map); + agent->set_paused(paused); + agent->set_radius(radius); + agent->set_height(height); + agent->set_position(position); + agent->set_avoidance_layers(avoidance_layers); + agent->set_avoidance_enabled(avoidance_enabled); + agent->set_use_3d_avoidance(use_3d_avoidance); + } +} + void NavObstacle::set_paused(bool p_paused) { if (paused == p_paused) { return; @@ -104,7 +217,7 @@ void NavObstacle::set_paused(bool p_paused) { map->add_obstacle(this); } } - //internal_update_agent(); + internal_update_agent(); } bool NavObstacle::get_paused() const { diff --git a/modules/navigation/nav_obstacle.h b/modules/navigation/nav_obstacle.h index cfd868fd3..f0d366dbe 100644 --- a/modules/navigation/nav_obstacle.h +++ b/modules/navigation/nav_obstacle.h @@ -34,18 +34,23 @@ #include "core/containers/local_vector.h" #include "core/object/class_db.h" -#include "nav_agent.h" #include "nav_rid.h" +class NavAgent; class NavMap; class NavObstacle : public NavRid { + NavAgent *agent; NavMap *map; + Vector3 velocity; Vector3 position; Vector vertices; + real_t radius; real_t height; + bool avoidance_enabled; + bool use_3d_avoidance; uint32_t avoidance_layers; bool obstacle_dirty; @@ -57,15 +62,30 @@ public: NavObstacle(); ~NavObstacle(); + void set_avoidance_enabled(bool p_enabled); + bool is_avoidance_enabled() { return avoidance_enabled; } + + void set_use_3d_avoidance(bool p_enabled); + bool get_use_3d_avoidance() { return use_3d_avoidance; } + void set_map(NavMap *p_map); NavMap *get_map() { return map; } + void set_agent(NavAgent *p_agent); + NavAgent *get_agent() { return agent; } + void set_position(const Vector3 p_position); const Vector3 &get_position() const { return position; } + void set_radius(real_t p_radius); + real_t get_radius() const { return radius; } + void set_height(const real_t p_height); real_t get_height() const { return height; } + void set_velocity(const Vector3 p_velocity); + const Vector3 &get_velocity() const { return velocity; } + void set_vertices(const Vector &p_vertices); const Vector &get_vertices() const { return vertices; } @@ -78,6 +98,9 @@ public: bool get_paused() const; bool check_dirty(); + +private: + void internal_update_agent(); }; #endif // NAV_OBSTACLE_H diff --git a/modules/navigation/pandemonium_navigation_2d_server.cpp b/modules/navigation/pandemonium_navigation_2d_server.cpp index e823cb227..b46f1d311 100644 --- a/modules/navigation/pandemonium_navigation_2d_server.cpp +++ b/modules/navigation/pandemonium_navigation_2d_server.cpp @@ -357,8 +357,12 @@ RID PandemoniumNavigation2DServer::obstacle_create() { RID obstacle = NavigationServer::get_singleton()->obstacle_create(); return obstacle; } +void FORWARD_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled, rid_to_rid, bool_to_bool); +bool FORWARD_1_C(obstacle_get_avoidance_enabled, RID, p_obstacle, rid_to_rid); void FORWARD_2(obstacle_set_map, RID, p_obstacle, RID, p_map, rid_to_rid, rid_to_rid); RID FORWARD_1_C(obstacle_get_map, RID, p_obstacle, rid_to_rid); +void FORWARD_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius, rid_to_rid, real_to_real); +void FORWARD_2(obstacle_set_velocity, RID, p_obstacle, Vector2, p_velocity, rid_to_rid, v2_to_v3); void FORWARD_2(obstacle_set_paused, RID, p_obstacle, bool, p_paused, rid_to_rid, bool_to_bool); bool FORWARD_1_C(obstacle_get_paused, RID, p_obstacle, rid_to_rid); void FORWARD_2(obstacle_set_position, RID, p_obstacle, Vector2, p_position, rid_to_rid, v2_to_v3); diff --git a/modules/navigation/pandemonium_navigation_2d_server.h b/modules/navigation/pandemonium_navigation_2d_server.h index 4e3c781d7..832755b3b 100644 --- a/modules/navigation/pandemonium_navigation_2d_server.h +++ b/modules/navigation/pandemonium_navigation_2d_server.h @@ -240,12 +240,14 @@ public: /// Creates the obstacle. virtual RID obstacle_create(); + virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled); + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const; virtual void obstacle_set_map(RID p_obstacle, RID p_map); virtual RID obstacle_get_map(RID p_obstacle) const; - + virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius); + virtual void obstacle_set_velocity(RID p_obstacle, Vector2 p_velocity); virtual void obstacle_set_paused(RID p_obstacle, bool p_paused); virtual bool obstacle_get_paused(RID p_obstacle) const; - virtual void obstacle_set_position(RID p_obstacle, Vector2 p_position); virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices); virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers); diff --git a/modules/navigation/pandemonium_navigation_server.cpp b/modules/navigation/pandemonium_navigation_server.cpp index ceeecf09c..c17bc116e 100644 --- a/modules/navigation/pandemonium_navigation_server.cpp +++ b/modules/navigation/pandemonium_navigation_server.cpp @@ -864,12 +864,48 @@ COMMAND_2(agent_set_avoidance_priority, RID, p_agent, real_t, p_priority) { RID PandemoniumNavigationServer::obstacle_create() { PandemoniumNavigationServer *mut_this = const_cast(this); MutexLock lock(mut_this->operations_mutex); + NavObstacle *obstacle = memnew(NavObstacle()); RID rid = obstacle_owner.make_rid(obstacle); obstacle->set_self(rid); + + NavAgent *agent = memnew(NavAgent()); + RID agent_rid = agent_owner.make_rid(agent); + agent->set_self(agent_rid); + + obstacle->set_agent(agent); + return rid; } +COMMAND_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled) { + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND(obstacle == nullptr); + + obstacle->set_avoidance_enabled(p_enabled); +} + +bool PandemoniumNavigationServer::obstacle_get_avoidance_enabled(RID p_obstacle) const { + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND_V(obstacle == nullptr, false); + + return obstacle->is_avoidance_enabled(); +} + +COMMAND_2(obstacle_set_use_3d_avoidance, RID, p_obstacle, bool, p_enabled) { + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND(obstacle == nullptr); + + obstacle->set_use_3d_avoidance(p_enabled); +} + +bool PandemoniumNavigationServer::obstacle_get_use_3d_avoidance(RID p_obstacle) const { + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND_V(obstacle == nullptr, false); + + return obstacle->get_use_3d_avoidance(); +} + COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map) { NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); ERR_FAIL_COND(obstacle == nullptr); @@ -916,12 +952,27 @@ bool PandemoniumNavigationServer::obstacle_get_paused(RID p_obstacle) const { return obstacle->get_paused(); } +COMMAND_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius) { + ERR_FAIL_COND_MSG(p_radius < 0.0, "Radius must be positive."); + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND(obstacle == nullptr); + + obstacle->set_radius(p_radius); +} + COMMAND_2(obstacle_set_height, RID, p_obstacle, real_t, p_height) { NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); ERR_FAIL_COND(obstacle == nullptr); obstacle->set_height(p_height); } +COMMAND_2(obstacle_set_velocity, RID, p_obstacle, Vector3, p_velocity) { + NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); + ERR_FAIL_COND(obstacle == nullptr); + + obstacle->set_velocity(p_velocity); +} + COMMAND_2(obstacle_set_position, RID, p_obstacle, Vector3, p_position) { NavObstacle *obstacle = obstacle_owner.getornull(p_obstacle); ERR_FAIL_COND(obstacle == nullptr); @@ -1007,9 +1058,17 @@ COMMAND_1(free, RID, p_object) { link_owner.free(p_object); } else if (agent_owner.owns(p_object)) { - NavAgent *agent = agent_owner.getornull(p_object); + internal_free_agent(p_object); + } else if (obstacle_owner.owns(p_object)) { + internal_free_obstacle(p_object); + } else { + ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed)."); + } +} - // Removes this agent from the map if assigned +void PandemoniumNavigationServer::internal_free_agent(RID p_object) { + NavAgent *agent = agent_owner.getornull(p_object); + if (agent) { if (agent->get_map() != nullptr) { agent->get_map()->remove_agent(agent); agent->set_map(nullptr); @@ -1017,19 +1076,26 @@ COMMAND_1(free, RID, p_object) { agent_owner.free(p_object); memdelete(agent); + } +} - } else if (obstacle_owner.owns(p_object)) { - NavObstacle *obstacle = obstacle_owner.getornull(p_object); - - // Removes this agent from the map if assigned +void PandemoniumNavigationServer::internal_free_obstacle(RID p_object) { + NavObstacle *obstacle = obstacle_owner.getornull(p_object); + if (obstacle) { if (obstacle->get_map() != nullptr) { obstacle->get_map()->remove_obstacle(obstacle); obstacle->set_map(nullptr); } + if (obstacle->get_agent()) { + if (obstacle->get_agent()->get_self() != RID()) { + RID _agent_rid = obstacle->get_agent()->get_self(); + obstacle->set_agent(nullptr); + internal_free_agent(_agent_rid); + } + } obstacle_owner.free(p_object); - } else { - ERR_PRINT("Attempted to free a NavigationServer RID that did not exist (or was already freed)."); + memdelete(obstacle); } } diff --git a/modules/navigation/pandemonium_navigation_server.h b/modules/navigation/pandemonium_navigation_server.h index 1b53c8808..cd67c9d6d 100644 --- a/modules/navigation/pandemonium_navigation_server.h +++ b/modules/navigation/pandemonium_navigation_server.h @@ -205,8 +205,14 @@ public: COMMAND_2(agent_set_avoidance_priority, RID, p_agent, real_t, p_priority); virtual RID obstacle_create(); + COMMAND_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled); + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const; + COMMAND_2(obstacle_set_use_3d_avoidance, RID, p_obstacle, bool, p_enabled); + virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const; COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map); virtual RID obstacle_get_map(RID p_obstacle) const; + COMMAND_2(obstacle_set_radius, RID, p_obstacle, real_t, p_radius); + COMMAND_2(obstacle_set_velocity, RID, p_obstacle, Vector3, p_velocity); COMMAND_2(obstacle_set_paused, RID, p_obstacle, bool, p_paused); virtual bool obstacle_get_paused(RID p_obstacle) const; COMMAND_2(obstacle_set_position, RID, p_obstacle, Vector3, p_position); @@ -224,6 +230,10 @@ public: virtual int get_process_info(ProcessInfo p_info) const; virtual NavigationUtilities::PathQueryResult _query_path(const NavigationUtilities::PathQueryParameters &p_parameters) const; + +private: + void internal_free_agent(RID p_object); + void internal_free_obstacle(RID p_object); }; #undef COMMAND_1 diff --git a/modules/navigation_dummy/dummy_navigation_2d_server.h b/modules/navigation_dummy/dummy_navigation_2d_server.h index d397ac617..e416fe64a 100644 --- a/modules/navigation_dummy/dummy_navigation_2d_server.h +++ b/modules/navigation_dummy/dummy_navigation_2d_server.h @@ -101,8 +101,12 @@ public: virtual RID obstacle_create() { return RID(); } virtual void obstacle_set_map(RID p_obstacle, RID p_map) {} virtual RID obstacle_get_map(RID p_obstacle) const { return RID(); } + virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) {} + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const { return false; } + virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius) {} virtual void obstacle_set_paused(RID p_obstacle, bool p_paused) {} virtual bool obstacle_get_paused(RID p_obstacle) const { return false; } + virtual void obstacle_set_velocity(RID p_obstacle, Vector2 p_velocity) {} virtual void obstacle_set_position(RID p_obstacle, Vector2 p_position) {} virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) {} virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) {} diff --git a/modules/navigation_dummy/dummy_navigation_server.h b/modules/navigation_dummy/dummy_navigation_server.h index 2f8747a7a..e0ea11a92 100644 --- a/modules/navigation_dummy/dummy_navigation_server.h +++ b/modules/navigation_dummy/dummy_navigation_server.h @@ -105,9 +105,15 @@ public: virtual RID obstacle_create() { return RID(); } virtual void obstacle_set_map(RID p_obstacle, RID p_map) {} virtual RID obstacle_get_map(RID p_obstacle) const { return RID(); } + virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) {} + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const { return false; } + virtual void obstacle_set_use_3d_avoidance(RID p_obstacle, bool p_enabled) {} + virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const { return false; } + virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius) {} virtual void obstacle_set_paused(RID p_obstacle, bool p_paused) {} virtual bool obstacle_get_paused(RID p_obstacle) const { return false; } virtual void obstacle_set_height(RID p_obstacle, real_t p_height) {} + virtual void obstacle_set_velocity(RID p_obstacle, Vector3 p_velocity) {} virtual void obstacle_set_position(RID p_obstacle, Vector3 p_position) {} virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) {} virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) {} diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index f7c43f9d9..465ce3beb 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -39,8 +39,10 @@ #include "servers/navigation_2d_server.h" void NavigationObstacle2D::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_obstacle_rid"), &NavigationObstacle2D::get_obstacle_rid); - ClassDB::bind_method(D_METHOD("get_agent_rid"), &NavigationObstacle2D::get_agent_rid); + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle2D::get_rid); + + ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationObstacle2D::set_avoidance_enabled); + ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationObstacle2D::get_avoidance_enabled); ClassDB::bind_method(D_METHOD("set_navigation", "navigation"), &NavigationObstacle2D::set_navigation_node); ClassDB::bind_method(D_METHOD("get_navigation"), &NavigationObstacle2D::get_navigation_node); @@ -62,7 +64,8 @@ void NavigationObstacle2D::_bind_methods() { ClassDB::bind_method(D_METHOD("set_avoidance_layer_value", "layer_number", "value"), &NavigationObstacle2D::set_avoidance_layer_value); ClassDB::bind_method(D_METHOD("get_avoidance_layer_value", "layer_number"), &NavigationObstacle2D::get_avoidance_layer_value); - ADD_GROUP("Avoidance", "avoidance_"); + ADD_GROUP("Avoidance", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_velocity", "get_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.0,500,0.01,suffix:px"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::POOL_VECTOR2_ARRAY, "vertices"), "set_vertices", "get_vertices"); @@ -92,7 +95,7 @@ void NavigationObstacle2D::_notification(int p_what) { previous_transform = get_global_transform(); // need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents - Navigation2DServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0); + Navigation2DServer::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); _update_position(get_global_transform().get_origin()); set_physics_process_internal(true); @@ -132,7 +135,7 @@ void NavigationObstacle2D::_notification(int p_what) { velocity_submitted = false; // only update if there is a noticeable change, else the rvo agent preferred velocity stays the same if (!previous_velocity.is_equal_approx(velocity)) { - Navigation2DServer::get_singleton()->agent_set_velocity(fake_agent, velocity); + Navigation2DServer::get_singleton()->obstacle_set_velocity(obstacle, velocity); } previous_velocity = velocity; } @@ -163,30 +166,24 @@ NavigationObstacle2D::NavigationObstacle2D() { navigation = NULL; obstacle = Navigation2DServer::get_singleton()->obstacle_create(); - fake_agent = Navigation2DServer::get_singleton()->agent_create(); - // change properties of the fake agent so it can act as fake obstacle with a radius - Navigation2DServer::get_singleton()->agent_set_neighbor_distance(fake_agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_max_neighbors(fake_agent, 0); - Navigation2DServer::get_singleton()->agent_set_time_horizon_agents(fake_agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_time_horizon_obstacles(fake_agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_max_speed(fake_agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_avoidance_mask(fake_agent, 0); - Navigation2DServer::get_singleton()->agent_set_avoidance_priority(fake_agent, 1.0); - Navigation2DServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0); + radius = 0.0; + + avoidance_enabled = true; + avoidance_layers = 1; + + velocity_submitted = false; set_radius(radius); set_vertices(vertices); set_avoidance_layers(avoidance_layers); + set_avoidance_enabled(avoidance_enabled); } NavigationObstacle2D::~NavigationObstacle2D() { ERR_FAIL_NULL(Navigation2DServer::get_singleton()); Navigation2DServer::get_singleton()->free(obstacle); obstacle = RID(); - - Navigation2DServer::get_singleton()->free(fake_agent); - fake_agent = RID(); } void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) { @@ -247,17 +244,19 @@ void NavigationObstacle2D::set_radius(real_t p_radius) { radius = p_radius; - Navigation2DServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0.0); - Navigation2DServer::get_singleton()->agent_set_radius(fake_agent, radius); + Navigation2DServer::get_singleton()->obstacle_set_radius(obstacle, radius); if (is_inside_tree() && (Engine::get_singleton()->is_editor_hint() || get_tree()->is_debugging_navigation_hint())) { update(); } } void NavigationObstacle2D::set_avoidance_layers(uint32_t p_layers) { + if (avoidance_layers == p_layers) { + return; + } + avoidance_layers = p_layers; Navigation2DServer::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers); - Navigation2DServer::get_singleton()->agent_set_avoidance_layers(fake_agent, avoidance_layers); } uint32_t NavigationObstacle2D::get_avoidance_layers() const { @@ -282,25 +281,31 @@ bool NavigationObstacle2D::get_avoidance_layer_value(int p_layer_number) const { return get_avoidance_layers() & (1 << (p_layer_number - 1)); } +void NavigationObstacle2D::set_avoidance_enabled(bool p_enabled) { + if (avoidance_enabled == p_enabled) { + return; + } + + avoidance_enabled = p_enabled; + Navigation2DServer::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); +} + +bool NavigationObstacle2D::get_avoidance_enabled() const { + return avoidance_enabled; +} + void NavigationObstacle2D::set_velocity(const Vector2 p_velocity) { velocity = p_velocity; velocity_submitted = true; - Navigation2DServer::get_singleton()->agent_set_velocity(fake_agent, velocity); } void NavigationObstacle2D::_update_map(RID p_map) { - Navigation2DServer::get_singleton()->obstacle_set_map(obstacle, p_map); - Navigation2DServer::get_singleton()->agent_set_map(fake_agent, p_map); map_current = p_map; + Navigation2DServer::get_singleton()->obstacle_set_map(obstacle, p_map); } void NavigationObstacle2D::_update_position(const Vector2 p_position) { - if (vertices.size() > 0) { - Navigation2DServer::get_singleton()->obstacle_set_position(obstacle, p_position); - } - if (radius > 0.0) { - Navigation2DServer::get_singleton()->agent_set_position(fake_agent, p_position); - } + Navigation2DServer::get_singleton()->obstacle_set_position(obstacle, p_position); } #ifdef DEBUG_ENABLED diff --git a/scene/2d/navigation_obstacle_2d.h b/scene/2d/navigation_obstacle_2d.h index 23d429ea5..2dd102741 100644 --- a/scene/2d/navigation_obstacle_2d.h +++ b/scene/2d/navigation_obstacle_2d.h @@ -45,18 +45,18 @@ class NavigationObstacle2D : public Node2D { RID map_override; RID map_current; - real_t radius = 0.0; + real_t radius; Vector vertices; - RID fake_agent; - uint32_t avoidance_layers = 1; + bool avoidance_enabled; + uint32_t avoidance_layers; Transform2D previous_transform; Vector2 velocity; Vector2 previous_velocity; - bool velocity_submitted = false; + bool velocity_submitted; #ifdef DEBUG_ENABLED private: @@ -80,8 +80,10 @@ public: void set_navigation_node(Node *p_nav); Node *get_navigation_node() const; - RID get_obstacle_rid() const { return obstacle; } - RID get_agent_rid() const { return fake_agent; } + RID get_rid() const { return obstacle; } + + void set_avoidance_enabled(bool p_enabled); + bool get_avoidance_enabled() const; void set_navigation_map(RID p_navigation_map); RID get_navigation_map() const; diff --git a/scene/3d/navigation_obstacle.cpp b/scene/3d/navigation_obstacle.cpp index 1ad10b4ee..8afecf032 100644 --- a/scene/3d/navigation_obstacle.cpp +++ b/scene/3d/navigation_obstacle.cpp @@ -43,8 +43,10 @@ #include "servers/rendering_server.h" void NavigationObstacle::_bind_methods() { - ClassDB::bind_method(D_METHOD("get_obstacle_rid"), &NavigationObstacle::get_obstacle_rid); - ClassDB::bind_method(D_METHOD("get_agent_rid"), &NavigationObstacle::get_agent_rid); + ClassDB::bind_method(D_METHOD("get_rid"), &NavigationObstacle::get_rid); + + ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationObstacle::set_avoidance_enabled); + ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationObstacle::get_avoidance_enabled); ClassDB::bind_method(D_METHOD("set_navigation_map", "navigation_map"), &NavigationObstacle::set_navigation_map); ClassDB::bind_method(D_METHOD("get_navigation_map"), &NavigationObstacle::get_navigation_map); @@ -78,7 +80,8 @@ void NavigationObstacle::_bind_methods() { ClassDB::bind_method(D_METHOD("_update_static_obstacle_debug"), &NavigationObstacle::_update_static_obstacle_debug); #endif // DEBUG_ENABLED - ADD_GROUP("Avoidance", "avoidance_"); + ADD_GROUP("Avoidance", ""); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "velocity", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_velocity", "get_velocity"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "radius", PROPERTY_HINT_RANGE, "0.0,100,0.01,suffix:m"), "set_radius", "get_radius"); ADD_PROPERTY(PropertyInfo(Variant::REAL, "height", PROPERTY_HINT_RANGE, "0.0,100,0.01,suffix:m"), "set_height", "get_height"); @@ -110,7 +113,7 @@ void NavigationObstacle::_notification(int p_what) { previous_transform = get_global_transform(); // need to trigger map controlled agent assignment somehow for the fake_agent since obstacles use no callback like regular agents - NavigationServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0); + NavigationServer::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); _update_position(get_global_transform().origin); set_physics_process_internal(true); @@ -166,7 +169,7 @@ void NavigationObstacle::_notification(int p_what) { velocity_submitted = false; // only update if there is a noticeable change, else the rvo agent preferred velocity stays the same if (!previous_velocity.is_equal_approx(velocity)) { - NavigationServer::get_singleton()->agent_set_velocity(fake_agent, velocity); + NavigationServer::get_singleton()->obstacle_set_velocity(obstacle, velocity); } previous_velocity = velocity; } @@ -195,24 +198,15 @@ NavigationObstacle::NavigationObstacle() { use_3d_avoidance = false; velocity_submitted = false; + avoidance_enabled = true; obstacle = NavigationServer::get_singleton()->obstacle_create(); - fake_agent = NavigationServer::get_singleton()->agent_create(); - - // change properties of the fake agent so it can act as fake obstacle with a radius - NavigationServer::get_singleton()->agent_set_neighbor_distance(fake_agent, 0.0); - NavigationServer::get_singleton()->agent_set_max_neighbors(fake_agent, 0); - NavigationServer::get_singleton()->agent_set_time_horizon_agents(fake_agent, 0.0); - NavigationServer::get_singleton()->agent_set_time_horizon_obstacles(fake_agent, 0.0); - NavigationServer::get_singleton()->agent_set_max_speed(fake_agent, 0.0); - NavigationServer::get_singleton()->agent_set_avoidance_mask(fake_agent, 1); - NavigationServer::get_singleton()->agent_set_avoidance_priority(fake_agent, 1.0); - NavigationServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0); set_radius(radius); set_height(height); set_vertices(vertices); set_avoidance_layers(avoidance_layers); + set_avoidance_enabled(avoidance_enabled); set_use_3d_avoidance(use_3d_avoidance); #ifdef DEBUG_ENABLED @@ -229,9 +223,6 @@ NavigationObstacle::~NavigationObstacle() { NavigationServer::get_singleton()->free(obstacle); obstacle = RID(); - NavigationServer::get_singleton()->free(fake_agent); - fake_agent = RID(); - #ifdef DEBUG_ENABLED NavigationServer::get_singleton()->disconnect("avoidance_debug_changed", this, "_update_fake_agent_radius_debug"); NavigationServer::get_singleton()->disconnect("avoidance_debug_changed", this, "_update_static_obstacle_debug"); @@ -258,7 +249,8 @@ void NavigationObstacle::set_navigation(Navigation *p_nav) { } navigation = p_nav; - NavigationServer::get_singleton()->agent_set_map(fake_agent, get_navigation_map()); + + NavigationServer::get_singleton()->obstacle_set_map(obstacle, get_navigation_map()); } void NavigationObstacle::set_navigation_node(Node *p_nav) { @@ -305,8 +297,7 @@ void NavigationObstacle::set_radius(real_t p_radius) { } radius = p_radius; - NavigationServer::get_singleton()->agent_set_avoidance_enabled(fake_agent, radius > 0.0); - NavigationServer::get_singleton()->agent_set_radius(fake_agent, radius); + NavigationServer::get_singleton()->obstacle_set_radius(obstacle, radius); #ifdef DEBUG_ENABLED _update_fake_agent_radius_debug(); @@ -321,7 +312,7 @@ void NavigationObstacle::set_height(real_t p_height) { height = p_height; NavigationServer::get_singleton()->obstacle_set_height(obstacle, height); - NavigationServer::get_singleton()->agent_set_height(fake_agent, height); + #ifdef DEBUG_ENABLED _update_static_obstacle_debug(); #endif // DEBUG_ENABLED @@ -330,7 +321,6 @@ void NavigationObstacle::set_height(real_t p_height) { void NavigationObstacle::set_avoidance_layers(uint32_t p_layers) { avoidance_layers = p_layers; NavigationServer::get_singleton()->obstacle_set_avoidance_layers(obstacle, avoidance_layers); - NavigationServer::get_singleton()->agent_set_avoidance_layers(fake_agent, avoidance_layers); } uint32_t NavigationObstacle::get_avoidance_layers() const { @@ -355,6 +345,19 @@ bool NavigationObstacle::get_avoidance_layer_value(int p_layer_number) const { return get_avoidance_layers() & (1 << (p_layer_number - 1)); } +void NavigationObstacle::set_avoidance_enabled(bool p_enabled) { + if (avoidance_enabled == p_enabled) { + return; + } + + avoidance_enabled = p_enabled; + NavigationServer::get_singleton()->obstacle_set_avoidance_enabled(obstacle, avoidance_enabled); +} + +bool NavigationObstacle::get_avoidance_enabled() const { + return avoidance_enabled; +} + void NavigationObstacle::set_use_3d_avoidance(bool p_use_3d_avoidance) { use_3d_avoidance = p_use_3d_avoidance; _update_use_3d_avoidance(use_3d_avoidance); @@ -367,28 +370,16 @@ void NavigationObstacle::set_velocity(const Vector3 p_velocity) { } void NavigationObstacle::_update_map(RID p_map) { - // avoidance obstacles are 2D only, no point keeping them on the map while 3D is used - if (use_3d_avoidance) { - NavigationServer::get_singleton()->obstacle_set_map(obstacle, RID()); - } else { - NavigationServer::get_singleton()->obstacle_set_map(obstacle, p_map); - } - NavigationServer::get_singleton()->agent_set_map(fake_agent, p_map); + NavigationServer::get_singleton()->obstacle_set_map(obstacle, p_map); map_current = p_map; } void NavigationObstacle::_update_position(const Vector3 p_position) { - if (vertices.size() > 0) { - NavigationServer::get_singleton()->obstacle_set_position(obstacle, p_position); - } - - if (radius > 0.0) { - NavigationServer::get_singleton()->agent_set_position(fake_agent, p_position); - } + NavigationServer::get_singleton()->obstacle_set_position(obstacle, p_position); } void NavigationObstacle::_update_use_3d_avoidance(bool p_use_3d_avoidance) { - NavigationServer::get_singleton()->agent_set_use_3d_avoidance(fake_agent, use_3d_avoidance); + NavigationServer::get_singleton()->obstacle_set_use_3d_avoidance(obstacle, use_3d_avoidance); _update_map(map_current); } diff --git a/scene/3d/navigation_obstacle.h b/scene/3d/navigation_obstacle.h index e540da444..33fec0c32 100644 --- a/scene/3d/navigation_obstacle.h +++ b/scene/3d/navigation_obstacle.h @@ -51,7 +51,7 @@ class NavigationObstacle : public Spatial { Vector vertices; - RID fake_agent; + bool avoidance_enabled; uint32_t avoidance_layers; bool use_3d_avoidance; @@ -90,8 +90,10 @@ public: void set_navigation_node(Node *p_nav); Node *get_navigation_node() const; - RID get_obstacle_rid() const { return obstacle; } - RID get_agent_rid() const { return fake_agent; } + RID get_rid() const { return obstacle; } + + void set_avoidance_enabled(bool p_enabled); + bool get_avoidance_enabled() const; void set_navigation_map(RID p_navigation_map); RID get_navigation_map() const; diff --git a/servers/navigation_2d_server.cpp b/servers/navigation_2d_server.cpp index 087c73687..8c3a924e2 100644 --- a/servers/navigation_2d_server.cpp +++ b/servers/navigation_2d_server.cpp @@ -124,8 +124,12 @@ void Navigation2DServer::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_set_avoidance_priority", "agent", "priority"), &Navigation2DServer::agent_set_avoidance_priority); ClassDB::bind_method(D_METHOD("obstacle_create"), &Navigation2DServer::obstacle_create); + ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_enabled", "obstacle", "enabled"), &Navigation2DServer::obstacle_set_avoidance_enabled); + ClassDB::bind_method(D_METHOD("obstacle_get_avoidance_enabled", "obstacle"), &Navigation2DServer::obstacle_get_avoidance_enabled); ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &Navigation2DServer::obstacle_set_map); ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &Navigation2DServer::obstacle_get_map); + ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &Navigation2DServer::obstacle_set_radius); + ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &Navigation2DServer::obstacle_set_velocity); ClassDB::bind_method(D_METHOD("obstacle_set_paused", "obstacle", "paused"), &Navigation2DServer::obstacle_set_paused); ClassDB::bind_method(D_METHOD("obstacle_get_paused", "obstacle"), &Navigation2DServer::obstacle_get_paused); ClassDB::bind_method(D_METHOD("obstacle_set_position", "obstacle", "position"), &Navigation2DServer::obstacle_set_position); diff --git a/servers/navigation_2d_server.h b/servers/navigation_2d_server.h index 8a01e090a..c3577e11f 100644 --- a/servers/navigation_2d_server.h +++ b/servers/navigation_2d_server.h @@ -249,10 +249,12 @@ public: virtual RID obstacle_create() = 0; virtual void obstacle_set_map(RID p_obstacle, RID p_map) = 0; virtual RID obstacle_get_map(RID p_obstacle) const = 0; - + virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) = 0; + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const = 0; + virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius) = 0; virtual void obstacle_set_paused(RID p_obstacle, bool p_paused) = 0; virtual bool obstacle_get_paused(RID p_obstacle) const = 0; - + virtual void obstacle_set_velocity(RID p_obstacle, Vector2 p_velocity) = 0; virtual void obstacle_set_position(RID p_obstacle, Vector2 p_position) = 0; virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) = 0; virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) = 0; diff --git a/servers/navigation_server.cpp b/servers/navigation_server.cpp index 783300841..150ec62f0 100644 --- a/servers/navigation_server.cpp +++ b/servers/navigation_server.cpp @@ -151,11 +151,17 @@ void NavigationServer::_bind_methods() { ClassDB::bind_method(D_METHOD("agent_set_avoidance_priority", "agent", "priority"), &NavigationServer::agent_set_avoidance_priority); ClassDB::bind_method(D_METHOD("obstacle_create"), &NavigationServer::obstacle_create); + ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_enabled", "obstacle", "enabled"), &NavigationServer::obstacle_set_avoidance_enabled); + ClassDB::bind_method(D_METHOD("obstacle_get_avoidance_enabled", "obstacle"), &NavigationServer::obstacle_get_avoidance_enabled); + ClassDB::bind_method(D_METHOD("obstacle_set_use_3d_avoidance", "obstacle", "enabled"), &NavigationServer::obstacle_set_use_3d_avoidance); + ClassDB::bind_method(D_METHOD("obstacle_get_use_3d_avoidance", "obstacle"), &NavigationServer::obstacle_get_use_3d_avoidance); ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &NavigationServer::obstacle_set_map); ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &NavigationServer::obstacle_get_map); + ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &NavigationServer::obstacle_set_radius); ClassDB::bind_method(D_METHOD("obstacle_set_paused", "obstacle", "paused"), &NavigationServer::obstacle_set_paused); ClassDB::bind_method(D_METHOD("obstacle_get_paused", "obstacle"), &NavigationServer::obstacle_get_paused); ClassDB::bind_method(D_METHOD("obstacle_set_height", "obstacle", "height"), &NavigationServer::obstacle_set_height); + ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &NavigationServer::obstacle_set_velocity); ClassDB::bind_method(D_METHOD("obstacle_set_position", "obstacle", "position"), &NavigationServer::obstacle_set_position); ClassDB::bind_method(D_METHOD("obstacle_set_vertices", "obstacle", "vertices"), &NavigationServer::obstacle_set_vertices); ClassDB::bind_method(D_METHOD("obstacle_set_avoidance_layers", "obstacle", "layers"), &NavigationServer::obstacle_set_avoidance_layers); diff --git a/servers/navigation_server.h b/servers/navigation_server.h index a685017e3..821f6f78d 100644 --- a/servers/navigation_server.h +++ b/servers/navigation_server.h @@ -268,11 +268,15 @@ public: virtual RID obstacle_create() = 0; virtual void obstacle_set_map(RID p_obstacle, RID p_map) = 0; virtual RID obstacle_get_map(RID p_obstacle) const = 0; - + virtual void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) = 0; + virtual bool obstacle_get_avoidance_enabled(RID p_obstacle) const = 0; + virtual void obstacle_set_use_3d_avoidance(RID p_obstacle, bool p_enabled) = 0; + virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const = 0; + virtual void obstacle_set_radius(RID p_obstacle, real_t p_radius) = 0; virtual void obstacle_set_paused(RID p_obstacle, bool p_paused) = 0; virtual bool obstacle_get_paused(RID p_obstacle) const = 0; - virtual void obstacle_set_height(RID p_obstacle, real_t p_height) = 0; + virtual void obstacle_set_velocity(RID p_obstacle, Vector3 p_velocity) = 0; virtual void obstacle_set_position(RID p_obstacle, Vector3 p_position) = 0; virtual void obstacle_set_vertices(RID p_obstacle, const Vector &p_vertices) = 0; virtual void obstacle_set_avoidance_layers(RID p_obstacle, uint32_t p_layers) = 0;