Replies: 1 comment
-
UPDATE: my bad, my velocity magnitude calculation was wrong by a factor of sqrt(2). I redid it and now all results are as expected. I kept my incorrect findings at the bottom under "OLD post". To sum up, in a side-view platformer:
(although I didn't try different slope angles so I'm not sure at 100% about the formula) This matches the expected values coming from dot product between intended motion and slope tangent. And unlike what I said in the old post, this is not case c., where a direct projection to a slope would be like case b. for 45 degrees, and yet something else for other angles. It's really just the application of some dot factor to the final motion delta. I suppose that the idea of determining how much we want to preserve of the original velocity is still relevant. For instance, when moving up a slope, we may want the character to use the same speed (velocity magnitude) as if moving horizontally. However, when moving down, it's another beast, as the extra velocity seems provided by snapping down to the ground; something I'm not sure move_and_slide has direct control with, considering incoming PR godotengine/godot#73749 is actually exposing current To come back to actual games for a pragmatic approach:
Finally, for platformers where character moves along the slope, the issue is minor because the character rarely enters the ground OLD post OK, so I tested the 2D platformer demo a bit and noticed that when moving up the 45-degree slope, the character is slower than in Godot 3, with a factor of 0.5 (ignoring gravity). That is, 75px/frame instead of 150px/frame. a. If snapping was purely vertical, horizontal speed would be preserved and the velocity magnitude would be increased by a factor of 1/sqrt(2)=1.41 when running up slopes. b. If velocity was purely preserved by rotating it until it matches the slope tangent, velocity magnitude would be equal to intended speed (150), so a factor of 1 would be applied. c. If snapping was done along ground normal, we'd have a factor of 1/sqrt(2)=0.707. (that was wrong too, this would be like b. in the case of a slope of 45 degrees) Where does the factor of 0.5 come from? Looking at godotengine/godot@d776b6c, I see an extra projection on motion_normal (so UP). If done on the first projection in case c, along slope tangent (diagonal), it would multiply again by 1/sqrt(2), for a total factor of 1/(sqrt(2)*sqrt(2))=1/2. That would explain it mathematically, but I'm not sure if that's the intended value. So before suggesting an alternative Then we can see that we really need. A bool to only apply case c. without extra factor? A tunable factor to change how much speed is preserved? etc. EDIT: edited discussion title to match new discussion topic |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
There is a classic issue when a character moves and slides near a collider, in a direction not perfectly aligned with the collider tangent, where it will slow down: the famous slow down when player tries to walk diagonally toward a horizontal or vertical wall in a top-view game.
Ex:
The same can occur in a side-view platformer when the character moves left and right on a slope.
Generally, the solution is to pass the velocity tangent to the current slope/wall directly. While platformers check for current ground anyway, top-view games may not bother caring about all walls in contact.
In this case, it may be interesting to have a variant of move_and_slide that preserves the full range of originally intended motion. It would basically resolve the sliding direction, but instead of applying a projection of the remaining motion vector, it would rotate it completely toward the new sliding direction (collider tangent).
I didn't post it as a suggestion because I want to know if there are already similar functions in Godot 4. In Godot 3, you can retrieve the resulting velocity from move_and_slide return value and reinject it for next frame.
In Godot 4, you can check
var last_collision = get_last_slide_collision()
and do something likedirection.rotated(last_collision.get_angle())
to get some direction along the tangent, but I'm not sure if this is the best (in my own projects, I just get the floor info directly from CharacterBody2D).Beta Was this translation helpful? Give feedback.
All reactions