Zylann / godot_voxel

Voxel module for Godot Engine
MIT License
2.58k stars 240 forks source link

how prevent rigidbody3d dont go through terrain and stop on top of it #676

Closed se8820726 closed 1 month ago

se8820726 commented 1 month ago

When applicable, please describe your setup:

i used Voxel game demos: https://github.com/Zylann/voxelgame/project/smooth_terrain/main.tcsn

then i made a rigidbody3d and a child collisionshape3d with default settings and when i played the scene the rigidbody went through the generated terrain and didnt stop on top of it. why ?

image
MGilleronFJ commented 1 month ago

This is a known "issue" with this module due to how it is designed.

Assuming you turned on collisions, this can happen because unlike regular Godot nodes, terrains in that module use dynamic streaming systems and threads. When the Godot scene starts (after freezing the game until every node is added to the tree), terrain won't be ready immediately. Instead, it progressively loads chunks around the player, and keeps doing so as they move, without blocking the game. So your rigidbody will fall through it if you let it run immediately before chunks around it have reached a high-enough LOD level to have collision.

There are several ways to deal with that:

You can have an animated loading screen in the meantime, pause the game (except the terrain which needs to keep processing) or prevent the player from simulating until either of those conditions are fulfilled.

Note: if you managed to go through in that demo due to colliders not having generated in time, either you were moving way too fast, or your computer is too slow for the setup you have, because it's usually unlikely for colliders to still not be ready when you get close to them.

Given how high your body is, another possible issue is that you simply experienced collision tunnelling, which is also a known issue in generally every physics engine when using mesh colliders. Voxel terrain must use mesh colliders because it can have any concave shape. The downside is if your body is too small and moves too fast, it can go through a mesh collider surface if it never gets to intersect that surface: frame 1 is in front of the surface not intersecting, frame 2 is beyond the surface still not intersecting, therefore the physics engine doesn't detect the collision. This is not unique to voxels, it happens with mesh colliders in general.

Some fixes for tunneling would be:

Note: in case you scaled your rigidbody, keep in mind this might not be well supported either, especially if you scaled it non-uniformly (it's not a box and your screen shows scaling gizmos so I suspect you did).


Finally, another simple cause is that you didn't have a VoxelViewer following your rigidbody. In that demo, there is a VoxelViewer under the camera, which tells the voxel engine to load chunks around it. But if the rigidbody doesn't have one, then it's going to get far from the camera, where there won't be chunks with collision anymore, and yeah, it will go through them.

The streaming system is mostly player-centric, so you can't expect to have collision everywhere beyond some distance from the player, it would be way too expensive. Or the player would have to closely follow that falling box. If you want a sharp collider everywhere you can see, then you pretty much have to forget about LOD and use VoxelTerrain.

If you really want to use VoxelLodTerrain and yet you really want bodies everywhere far from the player having collision with terrain, you could increase collision_lod_count so that more/every LOD has a collider, but they will snag when switching to higher/lower LODs as you move. A heavier approach would be to put a VoxelViewer on these bodies, so the terrain loads around them too (which in itself also makes things more expensive). The default streaming system of VoxelLodTerrain doesn't support multiple VoxelViewers, but there is an experimental system you can enable by changing the streaming_system property to CLIPBOX. Then you may also need to turn off visuals for these extra viewers because I assume you won't need that. That said, this feature is not well tested and might have issues. I'm not actively working on that area either at the moment so can't really help further there.


Sorry for the wall of text but as you can see with smooth voxel terrains with LOD and multi-threaded streaming, something that looks simple really isn't^^"

se8820726 commented 1 month ago

Both solutions you provided:

1- collision_lod_count 2- attach VoxelViewer to box

worked, and my problem is solved. Thank you.

However, the current issue is that, for example, I have a very large box, and I attach a VoxelViewer to it. Now, using the view distance property, I need to set the value so that the entire box fits within the view distance, which is quite difficult. It would be better to have a gizmo for the view distance value so that I can easily understand which area of the box falls within the view distance.

Thank you.

Zylann commented 1 month ago

If you have a physical moving box that is larger than the view distance of a VoxelViewer which also needs to fall, you might have quite big problems ahead in terms of simulation stability and performance...

There is no gizmo for viewers distance, but when you use Clipbox the terrain has a debug drawing property debug_draw_viewer_clipboxes that draws their chunk bounding volumes.