Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix NavigationAgent3D stored y-axis velocity and make it optional #83705

Merged
merged 1 commit into from
Oct 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
smix8 marked this conversation as resolved.
Show resolved Hide resolved
</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) {
smix8 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading