Browse Source

Merge pull request #59439 from fabriceci/3x-fix-move-and-collide-reported-collisions

Rémi Verschelde 3 years ago
parent
commit
841d6e7fad
4 changed files with 13 additions and 2 deletions
  1. 5 1
      scene/2d/physics_body_2d.cpp
  2. 1 0
      scene/2d/physics_body_2d.h
  3. 6 1
      scene/3d/physics_body.cpp
  4. 1 0
      scene/3d/physics_body.h

+ 5 - 1
scene/2d/physics_body_2d.cpp

@@ -991,7 +991,10 @@ void RigidBody2D::_reload_physics_characteristics() {
 Ref<KinematicCollision2D> KinematicBody2D::_move(const Vector2 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
 	Collision col;
 
-	if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
+	bool collided = move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only);
+
+	// Don't report collision when the whole motion is done.
+	if (collided && col.collision_safe_fraction < 1) {
 		// 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) {
 			motion_cache.instance();
@@ -1101,6 +1104,7 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_
 		r_collision.travel = result.motion;
 		r_collision.remainder = result.remainder;
 		r_collision.local_shape = result.collision_local_shape;
+		r_collision.collision_safe_fraction = result.collision_safe_fraction;
 	}
 
 	if (!p_test_only) {

+ 1 - 0
scene/2d/physics_body_2d.h

@@ -283,6 +283,7 @@ public:
 		Vector2 remainder;
 		Vector2 travel;
 		int local_shape;
+		real_t collision_safe_fraction;
 
 		real_t get_angle(const Vector2 &p_up_direction) const {
 			return Math::acos(normal.dot(p_up_direction));

+ 6 - 1
scene/3d/physics_body.cpp

@@ -959,7 +959,11 @@ void RigidBody::_reload_physics_characteristics() {
 
 Ref<KinematicCollision> KinematicBody::_move(const Vector3 &p_motion, bool p_infinite_inertia, bool p_exclude_raycast_shapes, bool p_test_only) {
 	Collision col;
-	if (move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only)) {
+
+	bool collided = move_and_collide(p_motion, p_infinite_inertia, col, p_exclude_raycast_shapes, p_test_only);
+
+	// Don't report collision when the whole motion is done.
+	if (collided && col.collision_safe_fraction < 1) {
 		// 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) {
 			motion_cache.instance();
@@ -1032,6 +1036,7 @@ bool KinematicBody::move_and_collide(const Vector3 &p_motion, bool p_infinite_in
 		r_collision.travel = result.motion;
 		r_collision.remainder = result.remainder;
 		r_collision.local_shape = result.collision_local_shape;
+		r_collision.collision_safe_fraction = result.collision_safe_fraction;
 	}
 
 	for (int i = 0; i < 3; i++) {

+ 1 - 0
scene/3d/physics_body.h

@@ -278,6 +278,7 @@ public:
 		Vector3 remainder;
 		Vector3 travel;
 		int local_shape;
+		real_t collision_safe_fraction;
 
 		real_t get_angle(const Vector3 &p_up_direction) const {
 			return Math::acos(normal.dot(p_up_direction));