Browse Source

Merge pull request #61235 from smix8/navigation_agent_avoidance_processing_4.x

Rémi Verschelde 3 years ago
parent
commit
a80793fcb8

+ 4 - 0
doc/classes/NavigationAgent2D.xml

@@ -42,6 +42,7 @@
 		<method name="get_rid" qualifiers="const">
 		<method name="get_rid" qualifiers="const">
 			<return type="RID" />
 			<return type="RID" />
 			<description>
 			<description>
+				Returns the [RID] of this agent on the [NavigationServer2D].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="get_target_location" qualifiers="const">
 		<method name="get_target_location" qualifiers="const">
@@ -84,6 +85,9 @@
 		</method>
 		</method>
 	</methods>
 	</methods>
 	<members>
 	<members>
+		<member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="false">
+			If [code]true[/code] the agent is registered for an RVO avoidance callback on the [NavigationServer2D]. When [method NavigationAgent2D.set_velocity] is used and the processing is completed a [code]safe_velocity[/code] Vector2 is received with a signal connection to [signal velocity_computed]. Avoidance processing with many registered agents has a significant performance cost and should only be enabled on agents that currently require it.
+		</member>
 		<member name="max_neighbors" type="int" setter="set_max_neighbors" getter="get_max_neighbors" default="10">
 		<member name="max_neighbors" type="int" setter="set_max_neighbors" getter="get_max_neighbors" default="10">
 			The maximum number of neighbors for the agent to consider.
 			The maximum number of neighbors for the agent to consider.
 		</member>
 		</member>

+ 4 - 0
doc/classes/NavigationAgent3D.xml

@@ -42,6 +42,7 @@
 		<method name="get_rid" qualifiers="const">
 		<method name="get_rid" qualifiers="const">
 			<return type="RID" />
 			<return type="RID" />
 			<description>
 			<description>
+				Returns the [RID] of this agent on the [NavigationServer3D].
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="get_target_location" qualifiers="const">
 		<method name="get_target_location" qualifiers="const">
@@ -87,6 +88,9 @@
 		<member name="agent_height_offset" type="float" setter="set_agent_height_offset" getter="get_agent_height_offset" default="0.0">
 		<member name="agent_height_offset" type="float" setter="set_agent_height_offset" getter="get_agent_height_offset" default="0.0">
 			The agent height offset to match the navigation mesh height.
 			The agent height offset to match the navigation mesh height.
 		</member>
 		</member>
+		<member name="avoidance_enabled" type="bool" setter="set_avoidance_enabled" getter="get_avoidance_enabled" default="false">
+			If [code]true[/code] the agent is registered for an RVO avoidance callback on the [NavigationServer3D]. When [method NavigationAgent3D.set_velocity] is used and the processing is completed a [code]safe_velocity[/code] Vector3 is received with a signal connection to [signal velocity_computed]. Avoidance processing with many registered agents has a significant performance cost and should only be enabled on agents that currently require it.
+		</member>
 		<member name="ignore_y" type="bool" setter="set_ignore_y" getter="get_ignore_y" default="true">
 		<member name="ignore_y" type="bool" setter="set_ignore_y" getter="get_ignore_y" default="true">
 			Ignores collisions on the Y axis. Must be true to move on a horizontal plane.
 			Ignores collisions on the Y axis. Must be true to move on a horizontal plane.
 		</member>
 		</member>

+ 19 - 2
scene/2d/navigation_agent_2d.cpp

@@ -37,6 +37,9 @@
 void NavigationAgent2D::_bind_methods() {
 void NavigationAgent2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent2D::get_rid);
 	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent2D::get_rid);
 
 
+	ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationAgent2D::set_avoidance_enabled);
+	ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationAgent2D::get_avoidance_enabled);
+
 	ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent2D::set_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent2D::set_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent2D::get_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent2D::get_target_desired_distance);
 
 
@@ -82,6 +85,7 @@ void NavigationAgent2D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:s"), "set_time_horizon", "get_time_horizon");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:s"), "set_time_horizon", "get_time_horizon");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,100000,0.01,suffix:px/s"), "set_max_speed", "get_max_speed");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "10,100,1,suffix:px"), "set_path_max_distance", "get_path_max_distance");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_2D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
 
 
 	ADD_SIGNAL(MethodInfo("path_changed"));
 	ADD_SIGNAL(MethodInfo("path_changed"));
@@ -97,7 +101,7 @@ void NavigationAgent2D::_notification(int p_what) {
 			if (agent_parent != nullptr) {
 			if (agent_parent != nullptr) {
 				// place agent on navigation map first or else the RVO agent callback creation fails silently later
 				// place agent on navigation map first or else the RVO agent callback creation fails silently later
 				NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map());
 				NavigationServer2D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_2d()->get_navigation_map());
-				NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+				set_avoidance_enabled(avoidance_enabled);
 			}
 			}
 			set_physics_process_internal(true);
 			set_physics_process_internal(true);
 		} break;
 		} break;
@@ -150,6 +154,19 @@ NavigationAgent2D::~NavigationAgent2D() {
 	agent = RID(); // Pointless
 	agent = RID(); // Pointless
 }
 }
 
 
+void NavigationAgent2D::set_avoidance_enabled(bool p_enabled) {
+	avoidance_enabled = p_enabled;
+	if (avoidance_enabled) {
+		NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+	} else {
+		NavigationServer2D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+	}
+}
+
+bool NavigationAgent2D::get_avoidance_enabled() const {
+	return avoidance_enabled;
+}
+
 void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
 void NavigationAgent2D::set_navigable_layers(uint32_t p_layers) {
 	bool layers_changed = navigable_layers != p_layers;
 	bool layers_changed = navigable_layers != p_layers;
 	navigable_layers = p_layers;
 	navigable_layers = p_layers;
@@ -268,7 +285,7 @@ TypedArray<String> NavigationAgent2D::get_configuration_warnings() const {
 	TypedArray<String> warnings = Node::get_configuration_warnings();
 	TypedArray<String> warnings = Node::get_configuration_warnings();
 
 
 	if (!Object::cast_to<Node2D>(get_parent())) {
 	if (!Object::cast_to<Node2D>(get_parent())) {
-		warnings.push_back(RTR("The NavigationAgent2D can be used only under a Node2D node."));
+		warnings.push_back(RTR("The NavigationAgent2D can be used only under a Node2D inheriting parent node."));
 	}
 	}
 
 
 	return warnings;
 	return warnings;

+ 4 - 0
scene/2d/navigation_agent_2d.h

@@ -43,6 +43,7 @@ class NavigationAgent2D : public Node {
 	RID agent;
 	RID agent;
 	RID map_before_pause;
 	RID map_before_pause;
 
 
+	bool avoidance_enabled = false;
 	uint32_t navigable_layers = 1;
 	uint32_t navigable_layers = 1;
 
 
 	real_t target_desired_distance = 1.0;
 	real_t target_desired_distance = 1.0;
@@ -78,6 +79,9 @@ public:
 		return agent;
 		return agent;
 	}
 	}
 
 
+	void set_avoidance_enabled(bool p_enabled);
+	bool get_avoidance_enabled() const;
+
 	void set_navigable_layers(uint32_t p_layers);
 	void set_navigable_layers(uint32_t p_layers);
 	uint32_t get_navigable_layers() const;
 	uint32_t get_navigable_layers() const;
 
 

+ 19 - 2
scene/3d/navigation_agent_3d.cpp

@@ -35,6 +35,9 @@
 void NavigationAgent3D::_bind_methods() {
 void NavigationAgent3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent3D::get_rid);
 	ClassDB::bind_method(D_METHOD("get_rid"), &NavigationAgent3D::get_rid);
 
 
+	ClassDB::bind_method(D_METHOD("set_avoidance_enabled", "enabled"), &NavigationAgent3D::set_avoidance_enabled);
+	ClassDB::bind_method(D_METHOD("get_avoidance_enabled"), &NavigationAgent3D::get_avoidance_enabled);
+
 	ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent3D::set_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("set_target_desired_distance", "desired_distance"), &NavigationAgent3D::set_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent3D::get_target_desired_distance);
 	ClassDB::bind_method(D_METHOD("get_target_desired_distance"), &NavigationAgent3D::get_target_desired_distance);
 
 
@@ -88,6 +91,7 @@ void NavigationAgent3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.1,10000,0.01,suffix:m/s"), "set_max_speed", "get_max_speed");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "path_max_distance", PROPERTY_HINT_RANGE, "0.01,100,0.1,suffix:m"), "set_path_max_distance", "get_path_max_distance");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "ignore_y"), "set_ignore_y", "get_ignore_y");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "avoidance_enabled"), "set_avoidance_enabled", "get_avoidance_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
 	ADD_PROPERTY(PropertyInfo(Variant::INT, "navigable_layers", PROPERTY_HINT_LAYERS_3D_NAVIGATION), "set_navigable_layers", "get_navigable_layers");
 
 
 	ADD_SIGNAL(MethodInfo("path_changed"));
 	ADD_SIGNAL(MethodInfo("path_changed"));
@@ -103,7 +107,7 @@ void NavigationAgent3D::_notification(int p_what) {
 			if (agent_parent != nullptr) {
 			if (agent_parent != nullptr) {
 				// place agent on navigation map first or else the RVO agent callback creation fails silently later
 				// place agent on navigation map first or else the RVO agent callback creation fails silently later
 				NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map());
 				NavigationServer3D::get_singleton()->agent_set_map(get_rid(), agent_parent->get_world_3d()->get_navigation_map());
-				NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+				set_avoidance_enabled(avoidance_enabled);
 			}
 			}
 			set_physics_process_internal(true);
 			set_physics_process_internal(true);
 		} break;
 		} break;
@@ -157,6 +161,19 @@ NavigationAgent3D::~NavigationAgent3D() {
 	agent = RID(); // Pointless
 	agent = RID(); // Pointless
 }
 }
 
 
+void NavigationAgent3D::set_avoidance_enabled(bool p_enabled) {
+	avoidance_enabled = p_enabled;
+	if (avoidance_enabled) {
+		NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done");
+	} else {
+		NavigationServer3D::get_singleton()->agent_set_callback(agent, nullptr, "_avoidance_done");
+	}
+}
+
+bool NavigationAgent3D::get_avoidance_enabled() const {
+	return avoidance_enabled;
+}
+
 void NavigationAgent3D::set_navigable_layers(uint32_t p_layers) {
 void NavigationAgent3D::set_navigable_layers(uint32_t p_layers) {
 	bool layers_changed = navigable_layers != p_layers;
 	bool layers_changed = navigable_layers != p_layers;
 	navigable_layers = p_layers;
 	navigable_layers = p_layers;
@@ -283,7 +300,7 @@ TypedArray<String> NavigationAgent3D::get_configuration_warnings() const {
 	TypedArray<String> warnings = Node::get_configuration_warnings();
 	TypedArray<String> warnings = Node::get_configuration_warnings();
 
 
 	if (!Object::cast_to<Node3D>(get_parent())) {
 	if (!Object::cast_to<Node3D>(get_parent())) {
-		warnings.push_back(RTR("The NavigationAgent3D can be used only under a spatial node."));
+		warnings.push_back(RTR("The NavigationAgent3D can be used only under a Node3D inheriting parent node."));
 	}
 	}
 
 
 	return warnings;
 	return warnings;

+ 4 - 0
scene/3d/navigation_agent_3d.h

@@ -43,6 +43,7 @@ class NavigationAgent3D : public Node {
 	RID agent;
 	RID agent;
 	RID map_before_pause;
 	RID map_before_pause;
 
 
+	bool avoidance_enabled = false;
 	uint32_t navigable_layers = 1;
 	uint32_t navigable_layers = 1;
 
 
 	real_t target_desired_distance = 1.0;
 	real_t target_desired_distance = 1.0;
@@ -80,6 +81,9 @@ public:
 		return agent;
 		return agent;
 	}
 	}
 
 
+	void set_avoidance_enabled(bool p_enabled);
+	bool get_avoidance_enabled() const;
+
 	void set_navigable_layers(uint32_t p_layers);
 	void set_navigable_layers(uint32_t p_layers);
 	uint32_t get_navigable_layers() const;
 	uint32_t get_navigable_layers() const;