Skip to content

Commit

Permalink
Merge pull request #83705 from smix8/agent_y_velocity_.4x
Browse files Browse the repository at this point in the history
Fix NavigationAgent3D stored y-axis velocity and make it optional
  • Loading branch information
akien-mga committed Oct 21, 2023
2 parents 0dc915b + 4771431 commit d2cd907
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
3 changes: 3 additions & 0 deletions doc/classes/NavigationAgent3D.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,9 @@
<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.
</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">
The maximum number of neighbors for the agent to consider.
</member>
Expand Down
27 changes: 26 additions & 1 deletion scene/3d/navigation_agent_3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("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("get_neighbor_distance"), &NavigationAgent3D::get_neighbor_distance);

Expand Down Expand Up @@ -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, "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, "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_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");
Expand Down Expand Up @@ -281,7 +285,9 @@ void NavigationAgent3D::_notification(int p_what) {
velocity_submitted = false;
if (avoidance_enabled) {
if (!use_3d_avoidance) {
stored_y_velocity = velocity.y;
if (keep_y_velocity) {
stored_y_velocity = velocity.y;
}
velocity.y = 0.0;
}
NavigationServer3D::get_singleton()->agent_set_velocity(agent, velocity);
Expand All @@ -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() {
agent = NavigationServer3D::get_singleton()->agent_create();

Expand Down Expand Up @@ -523,6 +538,15 @@ void NavigationAgent3D::set_use_3d_avoidance(bool p_use_3d_avoidance) {
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) {
if (Math::is_equal_approx(neighbor_distance, p_distance)) {
return;
Expand Down Expand Up @@ -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_velocity(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"));
break;
Expand Down
5 changes: 5 additions & 0 deletions scene/3d/navigation_agent_3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
// 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;

bool target_position_submitted = false;
Expand All @@ -114,6 +115,7 @@ class NavigationAgent3D : public Node {
protected:
static void _bind_methods();
void _notification(int p_what);
void _validate_property(PropertyInfo &p_property) const;

#ifndef DISABLE_DEPRECATED
bool _set(const StringName &p_name, const Variant &p_value);
Expand Down Expand Up @@ -173,6 +175,9 @@ class NavigationAgent3D : public Node {
void set_use_3d_avoidance(bool p_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);
real_t get_neighbor_distance() const { return neighbor_distance; }

Expand Down

0 comments on commit d2cd907

Please sign in to comment.