Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move_and_slide_with_snap fails to follow a moving platform if stop_on_slope is set to true #30311

Closed
Tracked by #50732 ...
Janders1800 opened this issue Jul 4, 2019 · 10 comments · Fixed by #51457
Closed
Tracked by #50732 ...

Comments

@Janders1800
Copy link

Janders1800 commented Jul 4, 2019

Godot version:
3.1.1

OS/device including version:
Zorin OS 12 Core (Ubuntu 16.04 LTS)

Issue description:
If a KinematicBody is on top of a moving platform will not move is stop_on_slope is set to true, this only happens if stop_on_slope is set to true, if is set to false it works OK.

https://youtu.be/QOzdqGwLxUg

Also the KinematicBody doesn't doesn't follow the rotation of the platform regardless of stop_on_slope.

Steps to reproduce:
Move a KinematicBody on top of a moving platform with stop_on_slope set to true

Bugsquad edit: MRP: kinematic_test.zip

@homchom
Copy link

homchom commented Sep 11, 2019

I think this affects move_and_slide (without snapping) as well. There's a chance I'm doing something wrong, but disabling stop_on_slope on my player node fixes moving platforms for me (which otherwise don't work, the player slides off). I'm using a 2D scene, so this may be unrelated.

@Duroxxigar
Copy link
Contributor

https://godotengine.org/article/godot-31-will-get-many-improvements-kinematicbody

According to this article, this kind of thing shouldn't really be an issue. @Janders1800 Are you moving the platform with the animation player? It seems like the "Sync To Physics" setting was never exposed for the 3D KinematicBody.

@Janders1800
Copy link
Author

Yeah, I'm moving the platform with the animation player.
I think it enters the category of issue since it works OK if stop_on _slope is set to false.

I don't know if it's a lack of implementation, but one would assume the function should behave the same, only changing its behavior according to the altered param.

@wyattjsmith1
Copy link

Yah, I am experiencing this too in 3.2.1. If I call move_and_slide_with_snap with stop_on_slope=true, the platform just moves below the character. If stop_on_slope=false, the moving platform moves the kinematic body with it.

I am using 3D with a KinematicBody character and a KinematicBody platform moving horizontally.

@AttackButton
Copy link
Contributor

AttackButton commented May 31, 2020

This happens in 2D too. And it still can be reproduced in version 3.2.2-beta3.

@robbertzzz
Copy link

Getting this in 2D too (3.2.1 stable), it took me half a day to debug this because I didn't know the stop_on_slope was the culprit.

@Calinou Calinou added this to the 4.0 milestone Jun 3, 2020
@nezvers
Copy link

nezvers commented Jul 1, 2020

In 3D I found out that I can have stop_on_slope withing move_and_slide_with_snap with slopes and with a moving platform. There's huge BUT.
If you want to stop on the slope you need to apply gravity even on the ground ( works with regular move_and_slide) BUT then moving platforms doesn't work.
If you want to move with a moving platform, don't apply gravity when grounded. In this configuration, you are slowly sliding down the slope even with velocity (0.0, 0.0, 0.0). There's also something I'd call a bug in 3D and 2D - player lags behind the moving platform.

@madmiraal
Copy link
Contributor

The core problem is that stop_on_slope is supposed to prevent sliding in a function that is designed for sliding. This results in both sliding occurring when it's not wanted (the frequent complaint) and no sliding occurring when it is wanted as is effectively the case presented in this issue.

The KinematicBody move_and_slide() function (also used by the move_and_slide_with_snap() function) will attempt to move the KinematicBody in the direction of the provided linear_velocity, a distance determined by the size of the linear_velocity and the delta. If it detects a collision it will change the direction of the linear_velocity to be perpendicular to the normal of the collision surface and then attempt to move KinematicBody the remaining distance. Any movement after the first collision is considered sliding.

The move_and_slide() function also simulates a KinematicBody being carried by a moving platform. The KinematicBody detects that it's on a platform if is_on_floor() was set to true in the previous call to move_and_slide(). For is_on_floor() to be true, it needs to collide with the platform. For it to collide with the platform there needs to be downward motion. So, if there was downward motion in the previous call and it collided with the platform, is_on_floor() will be true. If the KinematicBody detects that it's on a platform it will add the platform's velocity to it's linear_velocity. For the KinematicBody to be continually moved by the platform, there needs to be continuous downward motion to ensure is_on_floor() remains true for the next call. The result is, all the movement provided by the platform will be sliding, because it will immediately collide with the floor, have it's linear_velocity changed to be perpendicular to the floor and then slide along the floor. If the KinematicBody character is standing still, i.e. the linear_velocity provided is only the downward motion, the distance it slides will be exactly the distance moved by the platform. This provides the effect that the KinematicBody is moved by the platform.

The stop_on_slope parameter was designed to prevent a stationary KinematicBody character sliding down a slope due to the downward velocity used to simulate gravity being redirected down the slope. It does this by checking whether the linear_velocity passed to move_and_slide() only has a y-component i.e. the linear_velocity's x-component (and z-component in 3D) are zero. More specifically, it checks whether the linear_velocity is parallel (and in the opposite direction) to the normal of the surface it collides with. If so, and stop_on_slope is true, the sliding is reversed and the linear_velocity is set to 0. The result is, if a KinematicBody character is standing still and stop_on_slope is true, it will not slide down a slope.

The problem is, to simulate the KinematicBody being moved by the platform requires downward motion which results in sliding, while stop_on_slope reverses the effect of sliding if the character is standing still. Basically, when stop_on_slope is enabled, and the KinematicBody is standing still, all the sliding motion is reversed including the sliding providing the simulation of the KinematicBody being moved by the platform.

@Janders1800
Copy link
Author

Janders1800 commented Oct 7, 2020

Can't be temporally subtracted the linear velocity of the platform, so the check only takes into account the movement of the KinematicBody itself? regardless of its moving on a platform?

Or check the Y component of the linear velocity before adding the linear velocity of the platform?

Or add the linear velocity of the platform after cheeking the Y component?

@TokageItLab
Copy link
Member

TokageItLab commented Oct 8, 2020

There are two problems with the current stop_on_slope = true in move_and_slide_with_snap() as described in #42368.

  1. When stop_on_slope = true, if a vector of KinematicBody velocity is Down, it will not move the KinematicBody for preventing to slip. But, the vector of KinematicBody velocity does not include the floor velocity and the KinematicBody will not follow the moving floor.
  2. Correcting the coordinates when the KinematicBody collides with the moving slope causes the KinematicBody to slide down.

I think the first problem is a simple bug (and perhaps @Janders1800 is facing this problem). But the second problem is fundamentally in the implementation of stop_on_slope, as explained by @madmiraal above.

The floor velocity is calculate in several parts of move_and_slide() even though it doesn't work correctly in the current implementation, so adding and subtracting the floor velocity to KinematicBody velocity in GDScript won't make it work correctly. #42368 will fix the first problem and implement option of the attempting to discard calculation of the floor velocity for solving the second problem. So it will be able to apply user's coordinate calculation in GDScript on the moving platform.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.