Add agent pause mode to NavigationServer

Adds agent pause mode to NavigationServer.
This commit is contained in:
smix8 2023-06-15 15:35:53 +02:00
parent a83eb16fba
commit ae9dd47d0c
20 changed files with 194 additions and 26 deletions

View File

@ -38,6 +38,13 @@
Returns the navigation map [RID] the requested [param agent] is currently assigned to.
</description>
</method>
<method name="agent_get_paused" qualifiers="const">
<return type="bool" />
<param index="0" name="agent" type="RID" />
<description>
Returns [code]true[/code] if the specified [param agent] is paused.
</description>
</method>
<method name="agent_is_map_changed" qualifiers="const">
<return type="bool" />
<param index="0" name="agent" type="RID" />
@ -119,6 +126,14 @@
Sets the maximum distance to other agents this agent takes into account in the navigation. The larger this number, the longer the running time of the simulation. If the number is too low, the simulation will not be safe.
</description>
</method>
<method name="agent_set_paused">
<return type="void" />
<param index="0" name="agent" type="RID" />
<param index="1" name="paused" type="bool" />
<description>
If [param paused] is true the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks.
</description>
</method>
<method name="agent_set_position">
<return type="void" />
<param index="0" name="agent" type="RID" />
@ -478,6 +493,13 @@
Returns the navigation map [RID] the requested [param obstacle] is currently assigned to.
</description>
</method>
<method name="obstacle_get_paused" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
<description>
Returns [code]true[/code] if the specified [param obstacle] is paused.
</description>
</method>
<method name="obstacle_set_avoidance_enabled">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
@ -502,6 +524,14 @@
Sets the navigation map [RID] for the obstacle.
</description>
</method>
<method name="obstacle_set_paused">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="paused" type="bool" />
<description>
If [param paused] is true the specified [param obstacle] will not be processed, e.g. affect avoidance velocities.
</description>
</method>
<method name="obstacle_set_position">
<return type="void" />
<param index="0" name="obstacle" type="RID" />

View File

@ -38,6 +38,13 @@
Returns the navigation map [RID] the requested [param agent] is currently assigned to.
</description>
</method>
<method name="agent_get_paused" qualifiers="const">
<return type="bool" />
<param index="0" name="agent" type="RID" />
<description>
Returns [code]true[/code] if the specified [param agent] is paused.
</description>
</method>
<method name="agent_get_use_3d_avoidance" qualifiers="const">
<return type="bool" />
<param index="0" name="agent" type="RID" />
@ -134,6 +141,14 @@
Sets the maximum distance to other agents this agent takes into account in the navigation. The larger this number, the longer the running time of the simulation. If the number is too low, the simulation will not be safe.
</description>
</method>
<method name="agent_set_paused">
<return type="void" />
<param index="0" name="agent" type="RID" />
<param index="1" name="paused" type="bool" />
<description>
If [param paused] is true the specified [param agent] will not be processed, e.g. calculate avoidance velocities or receive avoidance callbacks.
</description>
</method>
<method name="agent_set_position">
<return type="void" />
<param index="0" name="agent" type="RID" />
@ -567,6 +582,13 @@
Returns the navigation map [RID] the requested [param obstacle] is currently assigned to.
</description>
</method>
<method name="obstacle_get_paused" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
<description>
Returns [code]true[/code] if the specified [param obstacle] is paused.
</description>
</method>
<method name="obstacle_get_use_3d_avoidance" qualifiers="const">
<return type="bool" />
<param index="0" name="obstacle" type="RID" />
@ -606,6 +628,14 @@
Assigns the [param obstacle] to a navigation map.
</description>
</method>
<method name="obstacle_set_paused">
<return type="void" />
<param index="0" name="obstacle" type="RID" />
<param index="1" name="paused" type="bool" />
<description>
If [param paused] is true the specified [param obstacle] will not be processed, e.g. affect avoidance velocities.
</description>
</method>
<method name="obstacle_set_position">
<return type="void" />
<param index="0" name="obstacle" type="RID" />

View File

@ -696,6 +696,20 @@ COMMAND_2(agent_set_map, RID, p_agent, RID, p_map) {
}
}
COMMAND_2(agent_set_paused, RID, p_agent, bool, p_paused) {
NavAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
agent->set_paused(p_paused);
}
bool GodotNavigationServer::agent_get_paused(RID p_agent) const {
NavAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND_V(agent == nullptr, false);
return agent->get_paused();
}
COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance) {
NavAgent *agent = agent_owner.get_or_null(p_agent);
ERR_FAIL_COND(agent == nullptr);
@ -889,6 +903,20 @@ RID GodotNavigationServer::obstacle_get_map(RID p_obstacle) const {
return RID();
}
COMMAND_2(obstacle_set_paused, RID, p_obstacle, bool, p_paused) {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND(obstacle == nullptr);
obstacle->set_paused(p_paused);
}
bool GodotNavigationServer::obstacle_get_paused(RID p_obstacle) const {
NavObstacle *obstacle = obstacle_owner.get_or_null(p_obstacle);
ERR_FAIL_COND_V(obstacle == nullptr, false);
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.get_or_null(p_obstacle);

View File

@ -184,6 +184,8 @@ public:
virtual bool agent_get_use_3d_avoidance(RID p_agent) const override;
COMMAND_2(agent_set_map, RID, p_agent, RID, p_map);
virtual RID agent_get_map(RID p_agent) const override;
COMMAND_2(agent_set_paused, RID, p_agent, bool, p_paused);
virtual bool agent_get_paused(RID p_agent) const override;
COMMAND_2(agent_set_neighbor_distance, RID, p_agent, real_t, p_distance);
COMMAND_2(agent_set_max_neighbors, RID, p_agent, int, p_count);
COMMAND_2(agent_set_time_horizon_agents, RID, p_agent, real_t, p_time_horizon);
@ -207,6 +209,8 @@ public:
virtual bool obstacle_get_use_3d_avoidance(RID p_obstacle) const override;
COMMAND_2(obstacle_set_map, RID, p_obstacle, RID, p_map);
virtual RID obstacle_get_map(RID p_obstacle) const override;
COMMAND_2(obstacle_set_paused, RID, p_obstacle, bool, p_paused);
virtual bool obstacle_get_paused(RID p_obstacle) const override;
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_position, RID, p_obstacle, Vector3, p_position);

View File

@ -342,3 +342,23 @@ const Dictionary NavAgent::get_avoidance_data() const {
}
return _avoidance_data;
}
void NavAgent::set_paused(bool p_paused) {
if (paused == p_paused) {
return;
}
paused = p_paused;
if (map) {
if (paused) {
map->remove_agent_as_controlled(this);
} else {
map->set_agent_as_controlled(this);
}
}
}
bool NavAgent::get_paused() const {
return paused;
}

View File

@ -73,6 +73,7 @@ class NavAgent : public NavRid {
bool agent_dirty = true;
uint32_t map_update_id = 0;
bool paused = false;
public:
NavAgent();
@ -138,6 +139,9 @@ public:
void set_avoidance_priority(real_t p_priority);
real_t get_avoidance_priority() const { return avoidance_priority; };
void set_paused(bool p_paused);
bool get_paused() const;
bool check_dirty();
// Updates this agent with rvo data after the rvo simulation avoidance step.

View File

@ -628,6 +628,11 @@ bool NavMap::has_obstacle(NavObstacle *obstacle) const {
}
void NavMap::add_obstacle(NavObstacle *obstacle) {
if (obstacle->get_paused()) {
// No point in adding a paused obstacle, it will add itself when unpaused again.
return;
}
if (!has_obstacle(obstacle)) {
obstacles.push_back(obstacle);
obstacles_dirty = true;
@ -644,6 +649,12 @@ void NavMap::remove_obstacle(NavObstacle *obstacle) {
void NavMap::set_agent_as_controlled(NavAgent *agent) {
remove_agent_as_controlled(agent);
if (agent->get_paused()) {
// No point in adding a paused agent, it will add itself when unpaused again.
return;
}
if (agent->get_use_3d_avoidance()) {
int64_t agent_3d_index = active_3d_avoidance_agents.find(agent);
if (agent_3d_index < 0) {

View File

@ -186,6 +186,7 @@ void NavObstacle::internal_update_agent() {
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);
@ -194,3 +195,24 @@ void NavObstacle::internal_update_agent() {
agent->set_use_3d_avoidance(use_3d_avoidance);
}
}
void NavObstacle::set_paused(bool p_paused) {
if (paused == p_paused) {
return;
}
paused = p_paused;
if (map) {
if (paused) {
map->remove_obstacle(this);
} else {
map->add_obstacle(this);
}
}
internal_update_agent();
}
bool NavObstacle::get_paused() const {
return paused;
}

View File

@ -56,6 +56,7 @@ class NavObstacle : public NavRid {
bool obstacle_dirty = true;
uint32_t map_update_id = 0;
bool paused = false;
public:
NavObstacle();
@ -93,6 +94,9 @@ public:
void set_avoidance_layers(uint32_t p_layers);
uint32_t get_avoidance_layers() const { return avoidance_layers; };
void set_paused(bool p_paused);
bool get_paused() const;
bool check_dirty();
private:

View File

@ -246,22 +246,14 @@ void NavigationAgent2D::_notification(int p_what) {
} break;
case NOTIFICATION_PAUSED: {
if (agent_parent && !agent_parent->can_process()) {
map_before_pause = NavigationServer2D::get_singleton()->agent_get_map(get_rid());
NavigationServer2D::get_singleton()->agent_set_map(get_rid(), RID());
} else if (agent_parent && agent_parent->can_process() && !(map_before_pause == RID())) {
NavigationServer2D::get_singleton()->agent_set_map(get_rid(), map_before_pause);
map_before_pause = RID();
if (agent_parent) {
NavigationServer2D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process());
}
} break;
case NOTIFICATION_UNPAUSED: {
if (agent_parent && !agent_parent->can_process()) {
map_before_pause = NavigationServer2D::get_singleton()->agent_get_map(get_rid());
NavigationServer2D::get_singleton()->agent_set_map(get_rid(), RID());
} else if (agent_parent && agent_parent->can_process() && !(map_before_pause == RID())) {
NavigationServer2D::get_singleton()->agent_set_map(get_rid(), map_before_pause);
map_before_pause = RID();
if (agent_parent) {
NavigationServer2D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process());
}
} break;

View File

@ -43,7 +43,6 @@ class NavigationAgent2D : public Node {
Node2D *agent_parent = nullptr;
RID agent;
RID map_before_pause;
RID map_override;
bool avoidance_enabled = false;

View File

@ -96,6 +96,7 @@ void NavigationObstacle2D::_notification(int p_what) {
_update_map(map_before_pause);
map_before_pause = RID();
}
NavigationServer2D::get_singleton()->obstacle_set_paused(obstacle, !can_process());
} break;
case NOTIFICATION_UNPAUSED: {
@ -106,6 +107,7 @@ void NavigationObstacle2D::_notification(int p_what) {
_update_map(map_before_pause);
map_before_pause = RID();
}
NavigationServer2D::get_singleton()->obstacle_set_paused(obstacle, !can_process());
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {

View File

@ -261,22 +261,14 @@ void NavigationAgent3D::_notification(int p_what) {
} break;
case NOTIFICATION_PAUSED: {
if (agent_parent && !agent_parent->can_process()) {
map_before_pause = NavigationServer3D::get_singleton()->agent_get_map(get_rid());
NavigationServer3D::get_singleton()->agent_set_map(get_rid(), RID());
} else if (agent_parent && agent_parent->can_process() && !(map_before_pause == RID())) {
NavigationServer3D::get_singleton()->agent_set_map(get_rid(), map_before_pause);
map_before_pause = RID();
if (agent_parent) {
NavigationServer3D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process());
}
} break;
case NOTIFICATION_UNPAUSED: {
if (agent_parent && !agent_parent->can_process()) {
map_before_pause = NavigationServer3D::get_singleton()->agent_get_map(get_rid());
NavigationServer3D::get_singleton()->agent_set_map(get_rid(), RID());
} else if (agent_parent && agent_parent->can_process() && !(map_before_pause == RID())) {
NavigationServer3D::get_singleton()->agent_set_map(get_rid(), map_before_pause);
map_before_pause = RID();
if (agent_parent) {
NavigationServer3D::get_singleton()->agent_set_paused(get_rid(), !agent_parent->can_process());
}
} break;

View File

@ -43,7 +43,6 @@ class NavigationAgent3D : public Node {
Node3D *agent_parent = nullptr;
RID agent;
RID map_before_pause;
RID map_override;
bool avoidance_enabled = false;

View File

@ -120,6 +120,7 @@ void NavigationObstacle3D::_notification(int p_what) {
_update_map(map_before_pause);
map_before_pause = RID();
}
NavigationServer3D::get_singleton()->obstacle_set_paused(obstacle, !can_process());
} break;
case NOTIFICATION_UNPAUSED: {
@ -130,6 +131,7 @@ void NavigationObstacle3D::_notification(int p_what) {
_update_map(map_before_pause);
map_before_pause = RID();
}
NavigationServer3D::get_singleton()->obstacle_set_paused(obstacle, !can_process());
} break;
case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: {

View File

@ -433,6 +433,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_get_avoidance_enabled", "agent"), &NavigationServer2D::agent_get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer2D::agent_get_map);
ClassDB::bind_method(D_METHOD("agent_set_paused", "agent", "paused"), &NavigationServer2D::agent_set_paused);
ClassDB::bind_method(D_METHOD("agent_get_paused", "agent"), &NavigationServer2D::agent_get_paused);
ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer2D::agent_set_neighbor_distance);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon_agents", "agent", "time_horizon"), &NavigationServer2D::agent_set_time_horizon_agents);
@ -453,6 +455,8 @@ void NavigationServer2D::_bind_methods() {
ClassDB::bind_method(D_METHOD("obstacle_get_avoidance_enabled", "obstacle"), &NavigationServer2D::obstacle_get_avoidance_enabled);
ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &NavigationServer2D::obstacle_set_map);
ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &NavigationServer2D::obstacle_get_map);
ClassDB::bind_method(D_METHOD("obstacle_set_paused", "obstacle", "paused"), &NavigationServer2D::obstacle_set_paused);
ClassDB::bind_method(D_METHOD("obstacle_get_paused", "obstacle"), &NavigationServer2D::obstacle_get_paused);
ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &NavigationServer2D::obstacle_set_radius);
ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &NavigationServer2D::obstacle_set_velocity);
ClassDB::bind_method(D_METHOD("obstacle_set_position", "obstacle", "position"), &NavigationServer2D::obstacle_set_position);
@ -594,6 +598,8 @@ void FORWARD_2(agent_set_velocity, RID, p_agent, Vector2, p_velocity, rid_to_rid
void FORWARD_2(agent_set_position, RID, p_agent, Vector2, p_position, rid_to_rid, v2_to_v3);
bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid);
void FORWARD_2(agent_set_paused, RID, p_agent, bool, p_paused, rid_to_rid, bool_to_bool);
bool FORWARD_1_C(agent_get_paused, RID, p_agent, rid_to_rid);
void FORWARD_1(free, RID, p_object, rid_to_rid);
void FORWARD_2(agent_set_avoidance_callback, RID, p_agent, Callable, p_callback, rid_to_rid, callable_to_callable);
@ -610,6 +616,8 @@ void FORWARD_2(obstacle_set_avoidance_enabled, RID, p_obstacle, bool, p_enabled,
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_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_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_position, RID, p_obstacle, Vector2, p_position, rid_to_rid, v2_to_v3);

View File

@ -178,6 +178,10 @@ public:
/// Put the agent in the map.
virtual void agent_set_map(RID p_agent, RID p_map);
virtual RID agent_get_map(RID p_agent) const;
virtual void agent_set_paused(RID p_agent, bool p_paused);
virtual bool agent_get_paused(RID p_agent) const;
virtual void agent_set_avoidance_enabled(RID p_agent, bool p_enabled);
virtual bool agent_get_avoidance_enabled(RID p_agent) const;
@ -244,6 +248,8 @@ public:
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_paused(RID p_obstacle, bool p_paused);
virtual bool obstacle_get_paused(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_position(RID p_obstacle, Vector2 p_position);

View File

@ -113,6 +113,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map);
ClassDB::bind_method(D_METHOD("agent_get_map", "agent"), &NavigationServer3D::agent_get_map);
ClassDB::bind_method(D_METHOD("agent_set_paused", "agent", "paused"), &NavigationServer3D::agent_set_paused);
ClassDB::bind_method(D_METHOD("agent_get_paused", "agent"), &NavigationServer3D::agent_get_paused);
ClassDB::bind_method(D_METHOD("agent_set_neighbor_distance", "agent", "distance"), &NavigationServer3D::agent_set_neighbor_distance);
ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors);
ClassDB::bind_method(D_METHOD("agent_set_time_horizon_agents", "agent", "time_horizon"), &NavigationServer3D::agent_set_time_horizon_agents);
@ -136,6 +138,8 @@ void NavigationServer3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("obstacle_get_use_3d_avoidance", "obstacle"), &NavigationServer3D::obstacle_get_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("obstacle_set_map", "obstacle", "map"), &NavigationServer3D::obstacle_set_map);
ClassDB::bind_method(D_METHOD("obstacle_get_map", "obstacle"), &NavigationServer3D::obstacle_get_map);
ClassDB::bind_method(D_METHOD("obstacle_set_paused", "obstacle", "paused"), &NavigationServer3D::obstacle_set_paused);
ClassDB::bind_method(D_METHOD("obstacle_get_paused", "obstacle"), &NavigationServer3D::obstacle_get_paused);
ClassDB::bind_method(D_METHOD("obstacle_set_radius", "obstacle", "radius"), &NavigationServer3D::obstacle_set_radius);
ClassDB::bind_method(D_METHOD("obstacle_set_height", "obstacle", "height"), &NavigationServer3D::obstacle_set_height);
ClassDB::bind_method(D_METHOD("obstacle_set_velocity", "obstacle", "velocity"), &NavigationServer3D::obstacle_set_velocity);

View File

@ -198,6 +198,9 @@ public:
virtual void agent_set_map(RID p_agent, RID p_map) = 0;
virtual RID agent_get_map(RID p_agent) const = 0;
virtual void agent_set_paused(RID p_agent, bool p_paused) = 0;
virtual bool agent_get_paused(RID p_agent) const = 0;
virtual void agent_set_avoidance_enabled(RID p_agent, bool p_enabled) = 0;
virtual bool agent_get_avoidance_enabled(RID p_agent) const = 0;
@ -264,6 +267,10 @@ 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_paused(RID p_obstacle, bool p_paused) = 0;
virtual bool obstacle_get_paused(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;

View File

@ -103,6 +103,8 @@ public:
RID agent_create() override { return RID(); }
void agent_set_map(RID p_agent, RID p_map) override {}
RID agent_get_map(RID p_agent) const override { return RID(); }
void agent_set_paused(RID p_agent, bool p_paused) override {}
bool agent_get_paused(RID p_agent) const override { return false; }
void agent_set_avoidance_enabled(RID p_agent, bool p_enabled) override {}
bool agent_get_avoidance_enabled(RID p_agent) const override { return false; }
void agent_set_use_3d_avoidance(RID p_agent, bool p_enabled) override {}
@ -125,6 +127,8 @@ public:
RID obstacle_create() override { return RID(); }
void obstacle_set_map(RID p_obstacle, RID p_map) override {}
RID obstacle_get_map(RID p_obstacle) const override { return RID(); }
void obstacle_set_paused(RID p_obstacle, bool p_paused) override {}
bool obstacle_get_paused(RID p_obstacle) const override { return false; }
void obstacle_set_avoidance_enabled(RID p_obstacle, bool p_enabled) override {}
bool obstacle_get_avoidance_enabled(RID p_obstacle) const override { return false; }
void obstacle_set_use_3d_avoidance(RID p_obstacle, bool p_enabled) override {}