Merge pull request #83705 from smix8/agent_y_velocity_.4x

Fix NavigationAgent3D stored y-axis velocity and make it optional
This commit is contained in:
Rémi Verschelde 2023-10-21 15:51:53 +02:00
commit d2cd907e28
No known key found for this signature in database
GPG Key ID: C3336907360768E1
3 changed files with 34 additions and 1 deletions

View File

@ -167,6 +167,9 @@
<member name="height" type="float" setter="set_height" getter="get_height" default="1.0"> <member name="height" type="float" setter="set_height" getter="get_height" default="1.0">
The height of the avoidance agent. Agents will ignore other agents or obstacles that are above or below their current position + height in 2D avoidance. Does nothing in 3D avoidance which uses radius spheres alone. The height of the avoidance agent. Agents will ignore other agents or obstacles that are above or below their current position + height in 2D avoidance. Does nothing in 3D avoidance which uses radius spheres alone.
</member> </member>
<member name="keep_y_velocity" type="bool" setter="set_keep_y_velocity" getter="get_keep_y_velocity" default="true">
If [code]true[/code] and the agent uses 2D avoidance it will remember the set y-axis velocity and reapply it after the avoidance step. While 2D avoidance has no y-axis and simulates on a flat plane this setting can help mitigate the most obvious clipping on uneven 3D geometry.
</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>

View File

@ -57,6 +57,9 @@ void NavigationAgent3D::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_use_3d_avoidance", "enabled"), &NavigationAgent3D::set_use_3d_avoidance); ClassDB::bind_method(D_METHOD("set_use_3d_avoidance", "enabled"), &NavigationAgent3D::set_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("get_use_3d_avoidance"), &NavigationAgent3D::get_use_3d_avoidance); ClassDB::bind_method(D_METHOD("get_use_3d_avoidance"), &NavigationAgent3D::get_use_3d_avoidance);
ClassDB::bind_method(D_METHOD("set_keep_y_velocity", "enabled"), &NavigationAgent3D::set_keep_y_velocity);
ClassDB::bind_method(D_METHOD("get_keep_y_velocity"), &NavigationAgent3D::get_keep_y_velocity);
ClassDB::bind_method(D_METHOD("set_neighbor_distance", "neighbor_distance"), &NavigationAgent3D::set_neighbor_distance); ClassDB::bind_method(D_METHOD("set_neighbor_distance", "neighbor_distance"), &NavigationAgent3D::set_neighbor_distance);
ClassDB::bind_method(D_METHOD("get_neighbor_distance"), &NavigationAgent3D::get_neighbor_distance); ClassDB::bind_method(D_METHOD("get_neighbor_distance"), &NavigationAgent3D::get_neighbor_distance);
@ -149,6 +152,7 @@ void NavigationAgent3D::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon_obstacles", PROPERTY_HINT_RANGE, "0.0,10,0.01,or_greater,suffix:s"), "set_time_horizon_obstacles", "get_time_horizon_obstacles"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "time_horizon_obstacles", PROPERTY_HINT_RANGE, "0.0,10,0.01,or_greater,suffix:s"), "set_time_horizon_obstacles", "get_time_horizon_obstacles");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.01,10000,0.01,or_greater,suffix:m/s"), "set_max_speed", "get_max_speed"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "max_speed", PROPERTY_HINT_RANGE, "0.01,10000,0.01,or_greater,suffix:m/s"), "set_max_speed", "get_max_speed");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_3d_avoidance"), "set_use_3d_avoidance", "get_use_3d_avoidance"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_3d_avoidance"), "set_use_3d_avoidance", "get_use_3d_avoidance");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_y_velocity"), "set_keep_y_velocity", "get_keep_y_velocity");
ADD_PROPERTY(PropertyInfo(Variant::INT, "avoidance_layers", PROPERTY_HINT_LAYERS_AVOIDANCE), "set_avoidance_layers", "get_avoidance_layers"); ADD_PROPERTY(PropertyInfo(Variant::INT, "avoidance_layers", PROPERTY_HINT_LAYERS_AVOIDANCE), "set_avoidance_layers", "get_avoidance_layers");
ADD_PROPERTY(PropertyInfo(Variant::INT, "avoidance_mask", PROPERTY_HINT_LAYERS_AVOIDANCE), "set_avoidance_mask", "get_avoidance_mask"); ADD_PROPERTY(PropertyInfo(Variant::INT, "avoidance_mask", PROPERTY_HINT_LAYERS_AVOIDANCE), "set_avoidance_mask", "get_avoidance_mask");
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "avoidance_priority", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_avoidance_priority", "get_avoidance_priority"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "avoidance_priority", PROPERTY_HINT_RANGE, "0.0,1.0,0.01"), "set_avoidance_priority", "get_avoidance_priority");
@ -281,7 +285,9 @@ void NavigationAgent3D::_notification(int p_what) {
velocity_submitted = false; velocity_submitted = false;
if (avoidance_enabled) { if (avoidance_enabled) {
if (!use_3d_avoidance) { if (!use_3d_avoidance) {
if (keep_y_velocity) {
stored_y_velocity = velocity.y; stored_y_velocity = velocity.y;
}
velocity.y = 0.0; velocity.y = 0.0;
} }
NavigationServer3D::get_singleton()->agent_set_velocity(agent, velocity); NavigationServer3D::get_singleton()->agent_set_velocity(agent, velocity);
@ -304,6 +310,15 @@ void NavigationAgent3D::_notification(int p_what) {
} }
} }
void NavigationAgent3D::_validate_property(PropertyInfo &p_property) const {
if (p_property.name == "keep_y_velocity") {
if (use_3d_avoidance) {
p_property.usage = PROPERTY_USAGE_NONE;
return;
}
}
}
NavigationAgent3D::NavigationAgent3D() { NavigationAgent3D::NavigationAgent3D() {
agent = NavigationServer3D::get_singleton()->agent_create(); agent = NavigationServer3D::get_singleton()->agent_create();
@ -523,6 +538,15 @@ void NavigationAgent3D::set_use_3d_avoidance(bool p_use_3d_avoidance) {
notify_property_list_changed(); notify_property_list_changed();
} }
void NavigationAgent3D::set_keep_y_velocity(bool p_enabled) {
keep_y_velocity = p_enabled;
stored_y_velocity = 0.0;
}
bool NavigationAgent3D::get_keep_y_velocity() const {
return keep_y_velocity;
}
void NavigationAgent3D::set_neighbor_distance(real_t p_distance) { void NavigationAgent3D::set_neighbor_distance(real_t p_distance) {
if (Math::is_equal_approx(neighbor_distance, p_distance)) { if (Math::is_equal_approx(neighbor_distance, p_distance)) {
return; return;
@ -807,6 +831,7 @@ void NavigationAgent3D::update_navigation() {
NavigationServer3D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); NavigationServer3D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin);
NavigationServer3D::get_singleton()->agent_set_velocity(agent, Vector3(0.0, 0.0, 0.0)); NavigationServer3D::get_singleton()->agent_set_velocity(agent, Vector3(0.0, 0.0, 0.0));
NavigationServer3D::get_singleton()->agent_set_velocity_forced(agent, Vector3(0.0, 0.0, 0.0)); NavigationServer3D::get_singleton()->agent_set_velocity_forced(agent, Vector3(0.0, 0.0, 0.0));
stored_y_velocity = 0.0;
} }
emit_signal(SNAME("navigation_finished")); emit_signal(SNAME("navigation_finished"));
break; break;

View File

@ -89,6 +89,7 @@ class NavigationAgent3D : public Node {
// 2D avoidance has no y-axis. This stores and reapplies the y-axis velocity to the agent before and after the avoidance step. // 2D avoidance has no y-axis. This stores and reapplies the y-axis velocity to the agent before and after the avoidance step.
// While not perfect it at least looks way better than agent's that clip through everything that is not a flat surface // While not perfect it at least looks way better than agent's that clip through everything that is not a flat surface
bool keep_y_velocity = true;
float stored_y_velocity = 0.0; float stored_y_velocity = 0.0;
bool target_position_submitted = false; bool target_position_submitted = false;
@ -114,6 +115,7 @@ class NavigationAgent3D : public Node {
protected: protected:
static void _bind_methods(); static void _bind_methods();
void _notification(int p_what); void _notification(int p_what);
void _validate_property(PropertyInfo &p_property) const;
#ifndef DISABLE_DEPRECATED #ifndef DISABLE_DEPRECATED
bool _set(const StringName &p_name, const Variant &p_value); bool _set(const StringName &p_name, const Variant &p_value);
@ -173,6 +175,9 @@ public:
void set_use_3d_avoidance(bool p_use_3d_avoidance); void set_use_3d_avoidance(bool p_use_3d_avoidance);
bool get_use_3d_avoidance() const { return use_3d_avoidance; } bool get_use_3d_avoidance() const { return use_3d_avoidance; }
void set_keep_y_velocity(bool p_enabled);
bool get_keep_y_velocity() const;
void set_neighbor_distance(real_t p_distance); void set_neighbor_distance(real_t p_distance);
real_t get_neighbor_distance() const { return neighbor_distance; } real_t get_neighbor_distance() const { return neighbor_distance; }