Zylann / godot_voxel

Voxel module for Godot Engine
Other
2.35k stars 224 forks source link

Unified Physics #618

Open ddel-rio opened 1 month ago

ddel-rio commented 1 month ago

Is your feature request related to a problem? Please describe. I am trying to recreate some Minecraft mechanics:

  1. Crouching: Prevents you from falling from high places while crouching.
  2. Body block: Makes two entities push each other so they can't occupy the same space.

I have tried to apply these features by combining BoxMover and Godot physics. However an unpleasant shaking occurs when the player interacts with non-terrain surfaces.

Describe the solution you'd like Due to the problems described above, I think a good solution would be to create a unified physics system. The developer should be able to create new objects called VoxelBody through code or nodes in the editor. These objects would be stored in an internal list and a simple physics solver would calculate the new positions of the colliding objects in a radius of 3x3 chunks. Optionally it could also be multithreading to improve performance.

Watching several YouTube tutorials (this is my favorite) I thought that implementing this system could be relatively simple and at the same time would add great value to the engine and solve many problems.

To do the crouching mechanic: It could predict which voxel the player is heading towards and if there is air below it it would create a static invisible collider that would prevent the player from moving any further.

Describe alternatives you've considered I've also considered using Godot's physics entirely, even for collision with terrain. But then the player would also collide with water or foliage and it would be very difficult to separate these elements in another terrain.

Additional context I am going to share an MRP that I have used to report some bugs in which you can check the difference that exists when trying to combine two different collision calculation systems.

mrp.zip

Try to collide in various ways with the big white cube.

Zylann commented 1 month ago

I'm aware that currently it might not be straightforward to combine the two, and I never really intented for both to be used at the same time. I think Godot physics is too expensive to use in blocky games (mainly because of how the terrain has to be handled and limitations of the API) so I haven't looked for ways to use it in my own tests, and I'm not sure whether it should be added. Meanwhile, even though "box physics" handles terrain better, it is relatively limited and might need improvements.

Note that this engine isn't only supporting Minecraft-like terrains, so adding a VoxelBody doing that would not be a good idea (I might use that name for something else). Perhaps a different name at least.

I currently have no plan/time to update this in the near future, although improvements are desirable. If someone can come up with improvements to box physics or some "mixed" physics alternative, it could start as a plugin or module, and could be merged if it's re-usable enough and the author is able to maintain it later on (or until I eventually look into this, which I can't tell when).

NuclearPhoenixx commented 4 weeks ago

Not sure what's the problem with using Godot Physics like you mentioned didn't work. If you're using Godot Physics, you can implement a crouch mechanic by using the test_move function and checking if you would collide with the floor at the position you're moving to. Using Godot's physics bodies would probably also allow you to do the body block by checking if you're colliding with another physics body (e.g. any npc) and then applying some force/movement in the opposite direction.

In order to not collide with fluids, you can adjust the collision layer of your fluid voxels. You'll probably need a different material for them anyways, at least due to the transparency.

The only downside I have seen so far using Godot Physics is that collisions with the terrain get very janky if you go to something like 100k blocks or more in some direction. Like move_and_slide not sliding anymore and "sticking" you to blocks instead, but I'm guessing this is some limitation with Godot Physics itself, probably something with the precision of coordinates hence why "Large World Coordinates" exist. Other than that, I cannot complain of any performance issues. But so far I haven't added anything that needs collision other than the player itself, so that might change quickly.

Zylann commented 3 weeks ago

Not sure what's the problem with using Godot Physics like you mentioned didn't work.

I didn't say it didn't work, it's that it's much slower, less reliable, and too generalist for blocky voxel games. As a consequence it lacks efficient ways of doing things, which in turn involve more effort to implement fast. Also it isn't what I made my blocky prototypes with, therefore I didn't focus on it. You may use one or the other, while mixing both might or might not work out in some cases. The task of "unified physics" itself is way too broad IMO. Of course GodotPhysics has a lot of other features you can use to do other things, but that's not really my point. As for features like ledge-crouching and soft-push between entities, they could be done without full-blown physics or any sort of unification, but some of it is highly specific and as I said, I simply dont have the bandwidth or motivation to work or think more about this area at the moment (same thing for many other features). Therefore it's currently stuff you have to implement/investigate, maybe even customize for your game.

In order to not collide with fluids, you can adjust the collision layer of your fluid voxels. You'll probably need a different material for them anyways, at least due to the transparency.

Note that you can already do this, models have per-surface collision settings. I wouldn't recommend water to be handled by Godot physics anyways.

Other than that, I cannot complain of any performance issues

I have measured it on my profiler, the cost is quite high. While meshing is fully multi-threaded, collision baking is much slower, and is still constrained to the main thread due to the lack of thread-safety guarantees (this might end up requiring to conditionally do it per physics engine backend, because for example the Jolt physics addon does not support creating collision shapes in threads, so 2 entire different code paths would have to be maintained; despite Jolt itself supporting that), and solving mesh collisions is inherently slower than implicit grid colliders (which Godot or Jolt don't have). Maybe you haven't seen those performance issues yet because the module already does a lot of work to hide this by time-slicing collision baking, and you might still be below your frame budget for now.

namenmalkav commented 2 weeks ago

i hope you can make this compatible with jolt the performance managing rigidbody3d compared with the default engine is a great improve currently trying to make a space engineers mockup and this terrain generator solves a lot of issues and was thinking on relay on the jolt physics to have performance on the blocky ship parts i dont know if with the this engine can do something similar like moving voxels amazing project btw

Zylann commented 2 weeks ago

i hope you can make this compatible with jolt

You can already use it. The main thing the module can't do with Jolt is multithreaded collider generation, because for some reason the Jolt extension doesn't support it (the module doesn't currently do it anyways, but while GodotPhysics might be eligible nowadays, the Jolt extension specifically isn't due to how it was implemented).

Also keep in mind this issue is about blocky terrain. I wouldn't recommend using that for moving things at the moment.

namenmalkav commented 2 weeks ago

adding jolt to the project godot crashes may be is time to repoort a new issue :(

Zylann commented 2 weeks ago

There can be multiple reasons for it to crash, but most likely ones are not because of the module, but rather GDExtension and GodotJolt. The module uses the Godot physics server API, and like the rest of Godot, it currently doesn't assume what physics engine is under the hood. It is supposed to work the same with GodotJolt, as a drop-in replacement. If you have a crash to report you may have to report this to GodotJolt and/or ask around on the GDExtension channel in Godot chat.

NuclearPhoenixx commented 1 week ago

adding jolt to the project godot crashes may be is time to repoort a new issue :(

That is probably an issue with your specific project honestly. I added jolt to mine (downloaded the latest release version) and it works just fine. Try to use the latest build of godot voxel and the latest release of jolt. To be extra sure, try to add jolt to a clean new project -- if it doesn't crash, it's something related to your game.