diff --git a/doc/classes/PhysicsBody2D.xml b/doc/classes/PhysicsBody2D.xml index e108ab6298..7775cfb2f9 100644 --- a/doc/classes/PhysicsBody2D.xml +++ b/doc/classes/PhysicsBody2D.xml @@ -30,7 +30,7 @@ Moves the body along the vector [code]linear_velocity[/code]. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - The body will stop if it collides. Returns a [KinematicCollision2D], which contains information about the collision. + 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. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details). @@ -50,8 +50,8 @@ Checks for collisions without moving the body. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - 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]linear_velocity[/code]. Returns [code]true[/code] if a collision would occur. - [code]collision[/code] is an optional object of type [KinematicCollision2D], which contains additional information about the collision (should there be one). + 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]linear_velocity[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + [code]collision[/code] is an optional object of type [KinematicCollision2D], which contains additional information about the collision when stopped, or when touching another body along the motion. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody2D.collision/safe_margin] for more details). diff --git a/doc/classes/PhysicsBody3D.xml b/doc/classes/PhysicsBody3D.xml index 8718c0caa2..9cf587f2e0 100644 --- a/doc/classes/PhysicsBody3D.xml +++ b/doc/classes/PhysicsBody3D.xml @@ -38,7 +38,7 @@ Moves the body along the vector [code]linear_velocity[/code]. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - The body will stop if it collides. Returns a [KinematicCollision3D], which contains information about the collision. + The body will stop if it collides. Returns a [KinematicCollision3D], 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. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details). [code]max_collisions[/code] allows to retrieve more than one collision result. @@ -68,8 +68,8 @@ Checks for collisions without moving the body. This method should be used in [method Node._physics_process] (or in a method called by [method Node._physics_process]), as it uses the physics step's [code]delta[/code] value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. - Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would occur. - [code]collision[/code] is an optional object of type [KinematicCollision3D], which contains additional information about the collision (should there be one). + Virtually sets the node's position, scale and rotation to that of the given [Transform3D], then tries to move the body along the vector [code]linear_velocity[/code]. Returns [code]true[/code] if a collision would stop the body from moving along the whole path. + [code]collision[/code] is an optional object of type [KinematicCollision3D], which contains additional information about the collision when stopped, or when touching another body along the motion. [code]safe_margin[/code] is the extra margin used for collision recovery (see [member CharacterBody3D.collision/safe_margin] for more details). [code]max_collisions[/code] allows to retrieve more than one collision result. diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 9d140f744f..5ec2a81108 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -133,9 +133,12 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer2D::MotionResult *r = nullptr; + PhysicsServer2D::MotionResult temp_result; if (r_collision.is_valid()) { // Needs const_cast because method bindings don't support non-const Ref. r = const_cast(&r_collision->result); + } else { + r = &temp_result; } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky. @@ -143,7 +146,14 @@ bool PhysicsBody2D::test_move(const Transform2D &p_from, const Vector2 &p_linear PhysicsServer2D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin); - return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), parameters, r); + 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; + } } TypedArray PhysicsBody2D::get_collision_exceptions() { diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index ea881b6d54..5cb7f431e3 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -174,9 +174,12 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear ERR_FAIL_COND_V(!is_inside_tree(), false); PhysicsServer3D::MotionResult *r = nullptr; + PhysicsServer3D::MotionResult temp_result; if (r_collision.is_valid()) { // Needs const_cast because method bindings don't support non-const Ref. r = const_cast(&r_collision->result); + } else { + r = &temp_result; } // Hack in order to work with calling from _process as well as from _physics_process; calling from thread is risky @@ -184,7 +187,14 @@ bool PhysicsBody3D::test_move(const Transform3D &p_from, const Vector3 &p_linear PhysicsServer3D::MotionParameters parameters(p_from, p_linear_velocity * delta, p_margin); - return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), parameters, r); + 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; + } } void PhysicsBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) {