Having trouble keeping character on ground when walking on curved surfaces

We’re working on a platformer game and we made our own player controller system that controls the player object’s velocity directly.

The player has a dynamic Rigidbody2D which is moved by setting the Rigidbody2D’s velocity every frame based on player inputs and other circumstances.

Player jumping and gravity is handled by this same system and can be configured using an animation curve.

This all works great, but the problem we ran into is if our player runs along a curved surface, or even a surface that sharply changes in incline, we can’t really get the player character to stick to the ground, instead thanks to the low gravity and high movement speed we have in the game it launches off the surface as if it were a ramp.

Here’s an animation to demonstrate the issue

We understand this happens because the player moves along a surface so fast in a single frame that it ends up in the air by the next frame, but games like Ori and The Will of the Wisp have high movement speed with low gravity and curved surfaces, and they seem to have solved this problem in a way that’s convincing enough.

We tried the following solutions:

  • Increasing the framerate of the physics by lowering the FixedUpdate interval. This helped somewhat but not in most cases.

  • Snapping the player back to the ground if it only slightly leaves the ground. This sort of worked but made movement incredibly jittery.

  • Trying to calculate where the player would be next frame if they walked along the curved surface without leaving the ground and snapping them to that position. Similar results to the above solution.

  • Having a temporarily high gravity while walking on a curved surface. This seems to work somewhat, but requires higher gravity with higher motion speeds and sharper curve angles. Also has the jittery effect, the player suddenly jumping forward in space and the high gravity sometimes embeds the player into the ground. Somewhat solves the problem but looks really janky.

I’m wondering if there’s a good standard solution to this kind of problem. We looked over the internet but couldn’t find anything we haven’t already tried ourselves.

1 Like

I wont give you code for this because its too much time. But i can give you some tip.

  1. add new class GroundCheck
  2. make 2 fields float targetDistance; string groundLayerMask
  3. method that returns Vector3 point on the ground under your character(Physics.Raycast(Vector3.down …) be sure to cast grond layer or you end up ray hitting player.
  4. now you have the point under your character and simply set character position.y to be point on the ground + targetDistance

Then you should figure out how to handle jump with this. You can just disable script while jump performed and when landed enable it.

Another solution is easy. But idk if it wouldn not cause bugs. Try clamp rigidbody.velocity.y between -float.minvalue to 0.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms