From bafc6372b2fee1d633f1ab85a34dc41cb8af3b27 Mon Sep 17 00:00:00 2001 From: fabriceci Date: Tue, 21 Feb 2023 22:34:44 +0100 Subject: Exposes the apply_floor_snap function to allow a snap to be made regardless of velocity. (cherry picked from commit 1381e6da4f695323853b24cf8d3632604b629133) --- doc/classes/CharacterBody2D.xml | 8 +++++++- doc/classes/CharacterBody3D.xml | 8 +++++++- scene/2d/physics_body_2d.cpp | 17 +++++++++++++++-- scene/2d/physics_body_2d.h | 2 ++ scene/3d/physics_body_3d.cpp | 13 +++++++++++-- scene/3d/physics_body_3d.h | 1 + 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/doc/classes/CharacterBody2D.xml b/doc/classes/CharacterBody2D.xml index ce7d1e18d7..c0cfc31407 100644 --- a/doc/classes/CharacterBody2D.xml +++ b/doc/classes/CharacterBody2D.xml @@ -15,6 +15,12 @@ https://godotengine.org/asset-library/asset/120 + + + + Allows to manually apply a snap to the floor regardless of the body's velocity. This function does nothing when [method is_on_floor] returns [code]true[/code]. + + @@ -152,7 +158,7 @@ Sets a snapping distance. When set to a value different from [code]0.0[/code], the body is kept attached to slopes when calling [method move_and_slide]. The snapping vector is determined by the given distance along the opposite direction of the [member up_direction]. - As long as the snapping vector is in contact with the ground and the body moves against [member up_direction], the body will remain attached to the surface. Snapping is not applied if the body moves along [member up_direction], so it will be able to detach from the ground when jumping. + As long as the snapping vector is in contact with the ground and the body moves against [member up_direction], the body will remain attached to the surface. Snapping is not applied if the body moves along [member up_direction], meaning it contains vertical rising velocity, so it will be able to detach from the ground when jumping or when the body is pushed up by something. If you want to apply a snap without taking into account the velocity, use [method apply_floor_snap]. If [code]true[/code], the body will not slide on slopes when calling [method move_and_slide] when the body is standing still. diff --git a/doc/classes/CharacterBody3D.xml b/doc/classes/CharacterBody3D.xml index 2ff207acb7..8b511e5a72 100644 --- a/doc/classes/CharacterBody3D.xml +++ b/doc/classes/CharacterBody3D.xml @@ -17,6 +17,12 @@ https://godotengine.org/asset-library/asset/678 + + + + Allows to manually apply a snap to the floor regardless of the body's velocity. This function does nothing when [method is_on_floor] returns [code]true[/code]. + + @@ -144,7 +150,7 @@ Sets a snapping distance. When set to a value different from [code]0.0[/code], the body is kept attached to slopes when calling [method move_and_slide]. The snapping vector is determined by the given distance along the opposite direction of the [member up_direction]. - As long as the snapping vector is in contact with the ground and the body moves against [member up_direction], the body will remain attached to the surface. Snapping is not applied if the body moves along [member up_direction], so it will be able to detach from the ground when jumping. + As long as the snapping vector is in contact with the ground and the body moves against [member up_direction], the body will remain attached to the surface. Snapping is not applied if the body moves along [member up_direction], meaning it contains vertical rising velocity, so it will be able to detach from the ground when jumping or when the body is pushed up by something. If you want to apply a snap without taking into account the velocity, use [method apply_floor_snap]. If [code]true[/code], the body will not slide on slopes when calling [method move_and_slide] when the body is standing still. diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 1721bcde3b..ba361c2656 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -1391,9 +1391,13 @@ void CharacterBody2D::_move_and_slide_floating(double p_delta) { first_slide = false; } } +void CharacterBody2D::apply_floor_snap() { + _apply_floor_snap(); +} -void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor) { - if (on_floor || !p_was_on_floor || p_vel_dir_facing_up) { +// Method that avoids the p_wall_as_floor parameter for the public method. +void CharacterBody2D::_apply_floor_snap(bool p_wall_as_floor) { + if (on_floor) { return; } @@ -1428,6 +1432,14 @@ void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_ } } +void CharacterBody2D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor) { + if (on_floor || !p_was_on_floor || p_vel_dir_facing_up) { + return; + } + + _apply_floor_snap(p_wall_as_floor); +} + bool CharacterBody2D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) { if (up_direction == Vector2() || on_floor || !p_was_on_floor || p_vel_dir_facing_up) { return false; @@ -1699,6 +1711,7 @@ void CharacterBody2D::_notification(int p_what) { void CharacterBody2D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody2D::move_and_slide); + ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody2D::apply_floor_snap); ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody2D::set_velocity); ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody2D::get_velocity); diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index 53bc5b7cd3..c4eb77d861 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -337,6 +337,7 @@ public: PLATFORM_ON_LEAVE_DO_NOTHING, }; bool move_and_slide(); + void apply_floor_snap(); const Vector2 &get_velocity() const; void set_velocity(const Vector2 &p_velocity); @@ -446,6 +447,7 @@ private: void set_up_direction(const Vector2 &p_up_direction); void _set_collision_direction(const PhysicsServer2D::MotionResult &p_result); void _set_platform_data(const PhysicsServer2D::MotionResult &p_result); + void _apply_floor_snap(bool p_wall_as_floor = false); void _snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up, bool p_wall_as_floor = false); protected: diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index c8cfcf7d7a..ab5b054bb3 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -1565,8 +1565,8 @@ void CharacterBody3D::_move_and_slide_floating(double p_delta) { } } -void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up) { - if (collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) { +void CharacterBody3D::apply_floor_snap() { + if (collision_state.floor) { return; } @@ -1601,6 +1601,14 @@ void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_ } } +void CharacterBody3D::_snap_on_floor(bool p_was_on_floor, bool p_vel_dir_facing_up) { + if (collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) { + return; + } + + apply_floor_snap(); +} + bool CharacterBody3D::_on_floor_if_snapped(bool p_was_on_floor, bool p_vel_dir_facing_up) { if (up_direction == Vector3() || collision_state.floor || !p_was_on_floor || p_vel_dir_facing_up) { return false; @@ -1954,6 +1962,7 @@ void CharacterBody3D::_notification(int p_what) { void CharacterBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("move_and_slide"), &CharacterBody3D::move_and_slide); + ClassDB::bind_method(D_METHOD("apply_floor_snap"), &CharacterBody3D::apply_floor_snap); ClassDB::bind_method(D_METHOD("set_velocity", "velocity"), &CharacterBody3D::set_velocity); ClassDB::bind_method(D_METHOD("get_velocity"), &CharacterBody3D::get_velocity); diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index 92d4726bb5..d141c1aaa2 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -354,6 +354,7 @@ public: PLATFORM_ON_LEAVE_DO_NOTHING, }; bool move_and_slide(); + void apply_floor_snap(); const Vector3 &get_velocity() const; void set_velocity(const Vector3 &p_velocity); -- cgit v1.2.3