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">
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>

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("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);
@ -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");
@ -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);
@ -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();
@ -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;
@ -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;

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.
// 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;
@ -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);
@ -173,6 +175,9 @@ public:
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; }