diff --git a/doc/classes/KinematicBody.xml b/doc/classes/KinematicBody.xml index a5ec96a153..7390d26a28 100644 --- a/doc/classes/KinematicBody.xml +++ b/doc/classes/KinematicBody.xml @@ -86,7 +86,7 @@ - Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision. + Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision], which contains information about the collision when stopped, or when touching another body along the motion. If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given. @@ -139,7 +139,8 @@ - Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. + Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + Use [method move_and_collide] instead for detecting collision with touching bodies. diff --git a/doc/classes/KinematicBody2D.xml b/doc/classes/KinematicBody2D.xml index 774df9f99a..8aaa743653 100644 --- a/doc/classes/KinematicBody2D.xml +++ b/doc/classes/KinematicBody2D.xml @@ -84,7 +84,7 @@ - Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision. + Moves the body along the vector [code]rel_vec[/code]. The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision when stopped, or when touching another body along the motion. If [code]test_only[/code] is [code]true[/code], the body does not move but the would-be collision information is given. @@ -129,7 +129,8 @@ - Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would occur. + Checks for collisions without moving the body. Virtually sets the node's position, scale and rotation to that of the given [Transform2D], then tries to move the body along the vector [code]rel_vec[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + Use [method move_and_collide] instead for detecting collision with touching bodies. diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 59eb41c4ec..4190d60b66 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -345,10 +345,21 @@ struct _RigidBody2DInOut { bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref &p_result) { Physics2DServer::MotionResult *r = nullptr; + Physics2DServer::MotionResult temp_result; if (p_result.is_valid()) { r = p_result->get_result_ptr(); + } else { + r = &temp_result; + } + + bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); + + if (colliding) { + // Don't report collision when the whole motion is done. + return (r->collision_safe_fraction < 1.0); + } else { + return false; } - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); } void RigidBody2D::_direct_state_changed(Object *p_state) { @@ -1299,7 +1310,15 @@ Vector2 KinematicBody2D::get_floor_velocity() const { bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia) { ERR_FAIL_COND_V(!is_inside_tree(), false); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin); + Physics2DServer::MotionResult result; + bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin, &result); + + if (colliding) { + // Don't report collision when the whole motion is done. + return (result.collision_safe_fraction < 1.0); + } else { + return false; + } } void KinematicBody2D::set_safe_margin(float p_margin) { diff --git a/scene/3d/physics_body.cpp b/scene/3d/physics_body.cpp index 18a0cff351..1aa8bcbd5a 100644 --- a/scene/3d/physics_body.cpp +++ b/scene/3d/physics_body.cpp @@ -1259,7 +1259,15 @@ Vector3 KinematicBody::get_floor_velocity() const { bool KinematicBody::test_move(const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia) { ERR_FAIL_COND_V(!is_inside_tree(), false); - return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); + PhysicsServer::MotionResult result; + bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, &result); + + if (colliding) { + // Don't report collision when the whole motion is done. + return (result.collision_safe_fraction < 1.0); + } else { + return false; + } } bool KinematicBody::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) {