3
\$\begingroup\$

I've been trying to wrap my head around this issue: in a 2D platformer game (but this may as well apply to 3D games) I want the character to "stick" to the surface that it's moving along and at the same time maintain the same velocity no matter the incline/decline of the current surface. Also, if my character's speed is 1 unit/sec and the current delta time is 0.25, I want it to travel exactly 0.25 units no matter the "shape" of the surface met along the way during the frame.

Naively, I started with this base logic (warning, pseudo-code incoming):

vel += acceleration * timeDelta;
movementDelta = vel * timeDelta;

hit = raycast(pos, downward);

if (hit)
{
    vectorAlongSurface = hit.normal * fancyLinearAlgebra;
    pos += vectorAlongSurface.Normalized * movementDelta.Magnitude;
}
else
{ 
    pos += movementDelta;
}

But this is correct only if my character moves along the same surface normal for the whole frame and it breaks pretty badly if during the frame the surface has different normals along the way. This can give the feeling that the speed at which the character is moving is inconsistent. To give you an example:

enter image description here

While I do expect answers like "just don't make your terrain like that" I'm also considering situations where my game might experience an unexpected lag and have to deal with a large time delta that might push the character through different surface normals during the same frame.

Any advice on how to properly handle this would be much appreciated. I was thinking about somehow tracing all the changes of surface inclination from the character's position to the "naive raycast hit" point, but that seems to be quite expensive, especially considering that all the enemy characters would have to do the same. There must be some simple solution to this that I'm not seeing. Or maybe there's a way to make the inconsistency of speed in the given example less noticeable/irrelevant?

Thank you guys.

\$\endgroup\$
  • 1
    \$\begingroup\$ Are you using a single edge or polygon collider for the entire jagged terrain surface, so we can iterate through its edges without doing repeated raycasts? \$\endgroup\$ – DMGregory Dec 7 '18 at 20:41
  • \$\begingroup\$ I haven't decided firmly yet, but most likely it won't be a single collider. But even if I did, I see issues with iterating: what if the polygon and/or edge collider has a large amount of points, then I'd have to have some form of spatial partitioning and neareast-neighbor search for the points (for finding the closest points to the character and the naive raycast hit) also knowledge of the order of points to know which direction to iterate to, etc. Also other things come to mind, such a hole between frame1 and frame2 positions where the "perfect" trajectory would have to include some falling. \$\endgroup\$ – mt_ Dec 7 '18 at 20:56
  • \$\begingroup\$ I'd really love to hear a solution that someone used in a released game. \$\endgroup\$ – mt_ Dec 7 '18 at 20:56
  • 1
    \$\begingroup\$ You're not wrong, that is all stuff you'd need to do in the worst case. The trick is that a raycast needs to do all that in the base case, so even saving some of that effort half the time could be a win, if sticking to platforms turns out to be a major part of your workload in a frame. \$\endgroup\$ – DMGregory Dec 7 '18 at 20:59
  • \$\begingroup\$ All right, I guess I'll start bracing myself for quite a complicated collider surface tracing solution. Thank you, sir. I'll keep this thread open in case someone shares some alternative solutions. \$\endgroup\$ – mt_ Dec 7 '18 at 21:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.