1
\$\begingroup\$

I found this bug in many big games and never expected to find it in my small game. Basically, while running around carelessly, you suddenly clip through the terrain and fall endlessly.

I momentarily fixed it by putting water below the terrain. So, after a while, you fall into a giant pool of water and can /unstuck without needing to die due to this stupid bug.

I also doubled the collision for the static body. The collision was created using Godot's "create trimesh static body" button on the viewport.

Doubling the collisions seems to have helped, and as of now, the problem appears to be solved... but isn't there a better method?

Because what if I didn't completely fix the problem? What if I made it so rare that I'm just not gonna encounter it until it's too late, do I have to add 3, 4 ,5 or even more collisions just to be sure?

My terran is very low poly so it doesn't really matter that i have to add 5 collisions or more, but it's just not right.

extra details

the player's max speed is 31 miles or 50 km per hour, has a cube for the legs collision and another cube for the torso collision

the terrain is made in blender from a flat plane that was distorted into a landscape.

the player clips throu terrain even when in the middle of the mesh so doesn't matter if it's the edge between two connected terrains.

the collision was applied automatically by godot.

\$\endgroup\$
5
  • \$\begingroup\$ What kind of collision representation does your player avatar use? \$\endgroup\$
    – DMGregory
    Commented Jul 20, 2023 at 11:45
  • \$\begingroup\$ Did it happen in seam between colliders? Since you say the collision shape was created "create trimesh static body"... does the mesh from which it was created have thickness? And, was the player character moving particularly fast when the incident happened? - As per solutions, increasing the margin of the collision shape comes to mind. \$\endgroup\$
    – Theraot
    Commented Jul 20, 2023 at 13:16
  • \$\begingroup\$ @DMGregory a cube for the legs and cube for the torso \$\endgroup\$
    – Cei
    Commented Jul 20, 2023 at 21:52
  • \$\begingroup\$ @Theraot running speed was set to 14 so multiplied by delta that's 14 meters per second, 31 miles or 50 kilometers per hour, did not happen at the margin and the mesh is just a plane distorted in blender, do you think extruding the mesh so it becomes double layered will fix the problem? \$\endgroup\$
    – Cei
    Commented Jul 20, 2023 at 21:54
  • \$\begingroup\$ Make sure those details are in your question. \$\endgroup\$
    – DMGregory
    Commented Jul 20, 2023 at 21:55

1 Answer 1

2
\$\begingroup\$

Introduction to how physic engines work

The way most physics engines out there work including GodotPhysics and Bullet is like this※:

  1. Move the objects first.
  2. Then check if they are breaking some constraint (including collisions and joints).
  3. Then move the objects so they are not breaking the constraints.

Since moving the objects so they are not breaking the constraints they were breaking might result in breaking other constraints, in practice the second and third steps are done multiple times. With a hard cap in how many times it will repeat them, as to avoid and infinite loop. If the hard cap is exceded, it might result in objects stuck inside of each other. In Godot you can configure the hard cap, search for "solver iterations" in Project Setting.

You, of course, do not see the intermediary steps of this process.

You can also imagine that if the character were moving fast enough, it would move to the other side of the terrain in a single step and never collide with it. That phenomenon is known tunneling.

And yes, this is virtually every physics engine, not just Godot's one.

※: Barring continuous collision detection (which is only available for RigidBody(2D) in Godot, btw).


How does the physic engine end up pushing the character down the terrain

As you know, we want the player character to be moving downwards according to gravity, so it collides with the ground. Now think about how that happens...

  • First the player character moves down, so it is clipping the terrain.
  • Then Godot sees that it is colliding.
  • So Godot pushes the player character outside of the terrain.

And now you can imagine how this goes wrong: It pushes the player character out the wrong direction.

Why would it do that?

While I can argue that modern physics engines have all they need to figure out from where the objects were moving before they collided and push them out in that direction... In practice many physics engine push the objects the way that it is closer. Because this requires less computations, and thus it means they can handle more collisions in the same time.

I don't know if in Godot having multiple colliders in the character would make it more likely to get pushed the wrong direction.

You might try switching between GodotPhysics and Bullet to see which handles this situation better.

Having thin terrain makes this more likely. Because your character would be partially on both sides of the terrain when it is colliding with it.

Regardless how unlikely it might be, it only has to go wrong once for the character to clip through the terrain, so we want the chance to be zero.


Solution with extra colliders

Duplicating the collider gives you a second chance that the player character will be pushed the correct way. And, assuming you place the duplicated collider slightly lower, it has even better chances.

If you want to fix this with with extra colliders, consider using a WorldBoundaryShape3D which is often used for infinite impassable walls for the boundary of your game world. The WorldBoundaryShape3D acts as if it had infinite thickness, it will only ever push in the same direction.


Solution with terrain thickness

Another solution is to give thickness to the terrain. And this is also the solution for clipping through other things where you can't afford a WorldBoundaryShape3D (e.g. walls).

Any thickness would minimize the problem simply because when clipping the amount of the characters would sticks out the other side would be less than the same situation with a thin collider... But tunneling and almost tunneling (moving mostly to the other side and getting pushed that way) might still be possible at high enough speeds.

So, to completely fix this using thickness, you want:

  1. Set a terminal speed (not just for falling, for everything). So you limit the velocity magnitud at which your character moves to that terminal speed.
  2. Compute which distance the player character would move in a single physics step at that terminal speed.
  3. Make the thickness of any physical obstacle greater than that distance. My advice is to use the double of the distance as minimum thickness. Although it should not be necessary assuming the character size is significantly greater than the computed distance. I rather not have to think about it.

So, how much time is a physics step? First of all, you have how many physics frame per second happen (which is in Project Settings under "physics/common/physics_ticks_per_second") and second you have how many physics steps it will do per frame (which is in Project Settings under "physics/common/max_physics_steps_per_frame").

By default, we would have that each physics frame is 1/60 of a second. And each frame has 8 steps, so each step is 1/8 of that. So each step is a 1/(60*8) of a second that is 1/480 of a second or 0.002083333333 s.

And I'm advising to double it, following that advice we can assume it is the double of the time, so 0.004166666666 s... And let us round that up to 0.005 s (which is fine since we are defining a minimum threshold).

So you take your terminal speed multiply it by 0.005 s and you have your minimum thickness.

If you changed the defaults so physics steps are longer, then you need to recalculate because this thickness might no longer be safe. But if you made the physics steps shorter, then the minimum thickness would be lower, meaning that whatever thickness you were using is till fine.

For example, for a terminal velocity of 14 m/s the minimum thickness is 0.07 m, and for a more realistic terminal velocity of 60 m/s it is 0.3 m.

I also want to note that there is another reason to have a minimum thickness to things - not just terrain - and that is light leaking. And that might be larger than what you need for physics.


About the seam between colliders

By the way, in the seam where colliders meet, you might have the situation where pushing the character out of one collider pushes it into the other... And that ultimately might result in pushing the character the wrong way.

You would solve that by having the colliders overlap... Which you can accomplish by making the colliders larger, or by adding extra colliders in the seams.

However, this problem is less common in Godot and other engines where collision shapes have a non-zero extra margin, because that makes it so that aligning the meshes result in colliders slightly overlap in practice.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .