Browse Source

Merge pull request #60599 from rburing/rest_on_recovery_param

Rémi Verschelde 3 years ago
parent
commit
03f240ba93

+ 4 - 0
doc/classes/PhysicsTestMotionParameters2D.xml

@@ -28,5 +28,9 @@
 		<member name="motion" type="Vector2" setter="set_motion" getter="get_motion" default="Vector2(0, 0)">
 		<member name="motion" type="Vector2" setter="set_motion" getter="get_motion" default="Vector2(0, 0)">
 			Motion vector to define the length and direction of the motion to test.
 			Motion vector to define the length and direction of the motion to test.
 		</member>
 		</member>
+		<member name="recovery_as_collision" type="bool" setter="set_recovery_as_collision_enabled" getter="is_recovery_as_collision_enabled" default="false">
+			If set to [code]true[/code], any depenetration from the recovery phase is reported as a collision; this is used e.g. by [method CharacterBody2D.move_and_slide] for improving floor detection when floor snapping is disabled.
+			If set to [code]false[/code], only collisions resulting from the motion are reported; this is used e.g. by [method PhysicsBody2D.move_and_collide].
+		</member>
 	</members>
 	</members>
 </class>
 </class>

+ 4 - 0
doc/classes/PhysicsTestMotionParameters3D.xml

@@ -31,5 +31,9 @@
 		<member name="motion" type="Vector3" setter="set_motion" getter="get_motion" default="Vector3(0, 0, 0)">
 		<member name="motion" type="Vector3" setter="set_motion" getter="get_motion" default="Vector3(0, 0, 0)">
 			Motion vector to define the length and direction of the motion to test.
 			Motion vector to define the length and direction of the motion to test.
 		</member>
 		</member>
+		<member name="recovery_as_collision" type="bool" setter="set_recovery_as_collision_enabled" getter="is_recovery_as_collision_enabled" default="false">
+			If set to [code]true[/code], any depenetration from the recovery phase is reported as a collision; this is used e.g. by [method CharacterBody3D.move_and_slide] for improving floor detection when floor snapping is disabled.
+			If set to [code]false[/code], only collisions resulting from the motion are detected; this is used e.g. by [method PhysicsBody3D.move_and_collide].
+		</member>
 	</members>
 	</members>
 </class>
 </class>

+ 9 - 12
scene/2d/physics_body_2d.cpp

@@ -56,13 +56,11 @@ PhysicsBody2D::~PhysicsBody2D() {
 
 
 Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin) {
 Ref<KinematicCollision2D> PhysicsBody2D::_move(const Vector2 &p_distance, bool p_test_only, real_t p_margin) {
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
+	parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
 
 
 	PhysicsServer2D::MotionResult result;
 	PhysicsServer2D::MotionResult result;
 
 
-	bool collided = move_and_collide(parameters, result, p_test_only);
-
-	// Don't report collision when the whole motion is done.
-	if (collided && result.collision_safe_fraction < 1) {
+	if (move_and_collide(parameters, result, p_test_only)) {
 		// Create a new instance when the cached reference is invalid or still in use in script.
 		// Create a new instance when the cached reference is invalid or still in use in script.
 		if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
 		if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
 			motion_cache.instantiate();
 			motion_cache.instantiate();
@@ -143,15 +141,9 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_distan
 	}
 	}
 
 
 	PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin);
 	PhysicsServer2D::MotionParameters parameters(p_from, p_distance, p_margin);
+	parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
 
 
-	bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
-
-	if (colliding) {
-		// Don't report collision when the whole motion is done.
-		return (r->collision_safe_fraction < 1.0);
-	} else {
-		return false;
-	}
+	return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r);
 }
 }
 
 
 TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
 TypedArray<PhysicsBody2D> PhysicsBody2D::get_collision_exceptions() {
@@ -1145,6 +1137,7 @@ bool CharacterBody2D::move_and_slide() {
 
 
 	if (!current_platform_velocity.is_equal_approx(Vector2())) {
 	if (!current_platform_velocity.is_equal_approx(Vector2())) {
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 		parameters.exclude_bodies.insert(platform_rid);
 		parameters.exclude_bodies.insert(platform_rid);
 		if (platform_object_id.is_valid()) {
 		if (platform_object_id.is_valid()) {
 			parameters.exclude_objects.insert(platform_object_id);
 			parameters.exclude_objects.insert(platform_object_id);
@@ -1203,6 +1196,7 @@ void CharacterBody2D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
 
 
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 
 
 		Vector2 prev_position = parameters.from.columns[2];
 		Vector2 prev_position = parameters.from.columns[2];
 
 
@@ -1359,6 +1353,7 @@ void CharacterBody2D::_move_and_slide_floating(double p_delta) {
 	bool first_slide = true;
 	bool first_slide = true;
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
 		PhysicsServer2D::MotionParameters parameters(get_global_transform(), motion, margin);
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 
 
 		PhysicsServer2D::MotionResult result;
 		PhysicsServer2D::MotionResult result;
 		bool collided = move_and_collide(parameters, result, false, false);
 		bool collided = move_and_collide(parameters, result, false, false);
@@ -1405,6 +1400,7 @@ void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_
 	real_t length = MAX(floor_snap_length, margin);
 	real_t length = MAX(floor_snap_length, margin);
 
 
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+	parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 	parameters.collide_separation_ray = true;
 	parameters.collide_separation_ray = true;
 
 
 	PhysicsServer2D::MotionResult result;
 	PhysicsServer2D::MotionResult result;
@@ -1440,6 +1436,7 @@ bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_f
 	real_t length = MAX(floor_snap_length, margin);
 	real_t length = MAX(floor_snap_length, margin);
 
 
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	PhysicsServer2D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
+	parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 	parameters.collide_separation_ray = true;
 	parameters.collide_separation_ray = true;
 
 
 	PhysicsServer2D::MotionResult result;
 	PhysicsServer2D::MotionResult result;

+ 10 - 12
scene/3d/physics_body_3d.cpp

@@ -94,13 +94,11 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) {
 Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, int p_max_collisions) {
 Ref<KinematicCollision3D> PhysicsBody3D::_move(const Vector3 &p_distance, bool p_test_only, real_t p_margin, int p_max_collisions) {
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), p_distance, p_margin);
 	parameters.max_collisions = p_max_collisions;
 	parameters.max_collisions = p_max_collisions;
+	parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
 
 
 	PhysicsServer3D::MotionResult result;
 	PhysicsServer3D::MotionResult result;
 
 
-	bool collided = move_and_collide(parameters, result, p_test_only);
-
-	// Don't report collision when the whole motion is done.
-	if (collided && result.collision_safe_fraction < 1) {
+	if (move_and_collide(parameters, result, p_test_only)) {
 		// Create a new instance when the cached reference is invalid or still in use in script.
 		// Create a new instance when the cached reference is invalid or still in use in script.
 		if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
 		if (motion_cache.is_null() || motion_cache->reference_get_count() > 1) {
 			motion_cache.instantiate();
 			motion_cache.instantiate();
@@ -184,15 +182,9 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_distan
 	}
 	}
 
 
 	PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin);
 	PhysicsServer3D::MotionParameters parameters(p_from, p_distance, p_margin);
+	parameters.recovery_as_collision = false; // Don't report collisions generated only from recovery.
 
 
-	bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
-
-	if (colliding) {
-		// Don't report collision when the whole motion is done.
-		return (r->collision_safe_fraction < 1.0);
-	} else {
-		return false;
-	}
+	return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r);
 }
 }
 
 
 void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
 void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {
@@ -1214,6 +1206,8 @@ bool CharacterBody3D::move_and_slide() {
 
 
 	if (!current_platform_velocity.is_equal_approx(Vector3())) {
 	if (!current_platform_velocity.is_equal_approx(Vector3())) {
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), current_platform_velocity * delta, margin);
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
+
 		parameters.exclude_bodies.insert(platform_rid);
 		parameters.exclude_bodies.insert(platform_rid);
 		if (platform_object_id.is_valid()) {
 		if (platform_object_id.is_valid()) {
 			parameters.exclude_objects.insert(platform_object_id);
 			parameters.exclude_objects.insert(platform_object_id);
@@ -1277,6 +1271,7 @@ void CharacterBody3D::_move_and_slide_grounded(double p_delta, bool p_was_on_flo
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
 		parameters.max_collisions = 4;
 		parameters.max_collisions = 4;
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 
 
 		PhysicsServer3D::MotionResult result;
 		PhysicsServer3D::MotionResult result;
 		bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
 		bool collided = move_and_collide(parameters, result, false, !sliding_enabled);
@@ -1521,6 +1516,7 @@ void CharacterBody3D::_move_and_slide_floating(double p_delta) {
 	bool first_slide = true;
 	bool first_slide = true;
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 	for (int iteration = 0; iteration < max_slides; ++iteration) {
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
 		PhysicsServer3D::MotionParameters parameters(get_global_transform(), motion, margin);
+		parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 
 
 		PhysicsServer3D::MotionResult result;
 		PhysicsServer3D::MotionResult result;
 		bool collided = move_and_collide(parameters, result, false, false);
 		bool collided = move_and_collide(parameters, result, false, false);
@@ -1575,6 +1571,7 @@ void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_
 
 
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	parameters.max_collisions = 4;
 	parameters.max_collisions = 4;
+	parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 	parameters.collide_separation_ray = true;
 	parameters.collide_separation_ray = true;
 
 
 	PhysicsServer3D::MotionResult result;
 	PhysicsServer3D::MotionResult result;
@@ -1610,6 +1607,7 @@ bool CharacterBody3D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_f
 
 
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	PhysicsServer3D::MotionParameters parameters(get_global_transform(), -up_direction * length, margin);
 	parameters.max_collisions = 4;
 	parameters.max_collisions = 4;
+	parameters.recovery_as_collision = true; // Also report collisions generated only from recovery.
 	parameters.collide_separation_ray = true;
 	parameters.collide_separation_ray = true;
 
 
 	PhysicsServer3D::MotionResult result;
 	PhysicsServer3D::MotionResult result;

+ 1 - 1
servers/physics_2d/godot_space_2d.cpp

@@ -874,7 +874,7 @@ bool GodotSpace2D::test_body_motion(GodotBody2D *p_body, const PhysicsServer2D::
 
 
 	bool collided = false;
 	bool collided = false;
 
 
-	if (recovered || (safe < 1)) {
+	if ((p_parameters.recovery_as_collision && recovered) || (safe < 1)) {
 		if (safe >= 1) {
 		if (safe >= 1) {
 			best_shape = -1; //no best shape with cast, reset to -1
 			best_shape = -1; //no best shape with cast, reset to -1
 		}
 		}

+ 1 - 1
servers/physics_3d/godot_space_3d.cpp

@@ -906,7 +906,7 @@ bool GodotSpace3D::test_body_motion(GodotBody3D *p_body, const PhysicsServer3D::
 	}
 	}
 
 
 	bool collided = false;
 	bool collided = false;
-	if (recovered || (safe < 1)) {
+	if ((p_parameters.recovery_as_collision && recovered) || (safe < 1)) {
 		if (safe >= 1) {
 		if (safe >= 1) {
 			best_shape = -1; //no best shape with cast, reset to -1
 			best_shape = -1; //no best shape with cast, reset to -1
 		}
 		}

+ 4 - 0
servers/physics_server_2d.cpp

@@ -505,12 +505,16 @@ void PhysicsTestMotionParameters2D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters2D::get_exclude_objects);
 	ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters2D::get_exclude_objects);
 	ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_objects);
 	ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters2D::set_exclude_objects);
 
 
+	ClassDB::bind_method(D_METHOD("is_recovery_as_collision_enabled"), &PhysicsTestMotionParameters2D::is_recovery_as_collision_enabled);
+	ClassDB::bind_method(D_METHOD("set_recovery_as_collision_enabled", "enabled"), &PhysicsTestMotionParameters2D::set_recovery_as_collision_enabled);
+
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from");
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "from"), "set_from", "get_from");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "recovery_as_collision"), "set_recovery_as_collision_enabled", "is_recovery_as_collision_enabled");
 }
 }
 
 
 ///////////////////////////////
 ///////////////////////////////

+ 4 - 0
servers/physics_server_2d.h

@@ -485,6 +485,7 @@ public:
 		bool collide_separation_ray = false;
 		bool collide_separation_ray = false;
 		RBSet<RID> exclude_bodies;
 		RBSet<RID> exclude_bodies;
 		RBSet<ObjectID> exclude_objects;
 		RBSet<ObjectID> exclude_objects;
+		bool recovery_as_collision = false;
 
 
 		MotionParameters() {}
 		MotionParameters() {}
 
 
@@ -727,6 +728,9 @@ public:
 
 
 	Array get_exclude_objects() const;
 	Array get_exclude_objects() const;
 	void set_exclude_objects(const Array &p_exclude);
 	void set_exclude_objects(const Array &p_exclude);
+
+	bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
+	void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
 };
 };
 
 
 class PhysicsTestMotionResult2D : public RefCounted {
 class PhysicsTestMotionResult2D : public RefCounted {

+ 4 - 0
servers/physics_server_3d.cpp

@@ -527,6 +527,9 @@ void PhysicsTestMotionParameters3D::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters3D::get_exclude_objects);
 	ClassDB::bind_method(D_METHOD("get_exclude_objects"), &PhysicsTestMotionParameters3D::get_exclude_objects);
 	ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_objects);
 	ClassDB::bind_method(D_METHOD("set_exclude_objects", "exclude_list"), &PhysicsTestMotionParameters3D::set_exclude_objects);
 
 
+	ClassDB::bind_method(D_METHOD("is_recovery_as_collision_enabled"), &PhysicsTestMotionParameters3D::is_recovery_as_collision_enabled);
+	ClassDB::bind_method(D_METHOD("set_recovery_as_collision_enabled", "enabled"), &PhysicsTestMotionParameters3D::set_recovery_as_collision_enabled);
+
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from");
 	ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM3D, "from"), "set_from", "get_from");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion");
 	ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "motion"), "set_motion", "get_motion");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
 	ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin"), "set_margin", "get_margin");
@@ -534,6 +537,7 @@ void PhysicsTestMotionParameters3D::_bind_methods() {
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_separation_ray"), "set_collide_separation_ray_enabled", "is_collide_separation_ray_enabled");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_bodies", PROPERTY_HINT_ARRAY_TYPE, "RID"), "set_exclude_bodies", "get_exclude_bodies");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
 	ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude_objects"), "set_exclude_objects", "get_exclude_objects");
+	ADD_PROPERTY(PropertyInfo(Variant::BOOL, "recovery_as_collision"), "set_recovery_as_collision_enabled", "is_recovery_as_collision_enabled");
 }
 }
 
 
 ///////////////////////////////
 ///////////////////////////////

+ 4 - 0
servers/physics_server_3d.h

@@ -522,6 +522,7 @@ public:
 		bool collide_separation_ray = false;
 		bool collide_separation_ray = false;
 		RBSet<RID> exclude_bodies;
 		RBSet<RID> exclude_bodies;
 		RBSet<ObjectID> exclude_objects;
 		RBSet<ObjectID> exclude_objects;
+		bool recovery_as_collision = false;
 
 
 		MotionParameters() {}
 		MotionParameters() {}
 
 
@@ -941,6 +942,9 @@ public:
 
 
 	Array get_exclude_objects() const;
 	Array get_exclude_objects() const;
 	void set_exclude_objects(const Array &p_exclude);
 	void set_exclude_objects(const Array &p_exclude);
+
+	bool is_recovery_as_collision_enabled() const { return parameters.recovery_as_collision; }
+	void set_recovery_as_collision_enabled(bool p_enabled) { parameters.recovery_as_collision = p_enabled; }
 };
 };
 
 
 class PhysicsTestMotionResult3D : public RefCounted {
 class PhysicsTestMotionResult3D : public RefCounted {