idanarye / bevy-tnua

A floating character controller for Bevy
https://crates.io/crates/bevy-tnua
Apache License 2.0
235 stars 16 forks source link

Kinematic "physics" backend #36

Closed dror-g closed 10 months ago

dror-g commented 10 months ago

Suggestion - add a kinematic character control backend option.

Physics systems like Xpbd & Rapier add a lot of overhead (even with reduced accuracy settings) and are often overkill for many types of games.

Tnua has a lot of features that are useful even without physics, such as animation helpers, states and general abstraction. It would be very beneficial to have a lightweight option to preserve these features in resource-constrained environments.

I believe there was a kinematic mode in earlier versions? perhaps not too difficult to implement?

Thanks for this amazing crate!!!

idanarye commented 10 months ago

I'm not even sure what something like this would even mean...

Tnua, for its bare minimum behavior, requires 3 things from the physics backends:

The physics integration layer has some more API components, but they are used for more advanced stuff. These three are the bare minimum, and without them Tnua won't be able to function at all.

For a game, being without a physics system could mean one of two things - either there is no spatial elements in the gameplay (card games, visual novels, RPGs or time management games where there are not maps to walk around or fight at - only "rooms"), or the game has its own basic physics engine (so that can be motion and that you won't be able to walk into walls)

For the former, Tnua is completely irrelevant. For the latter - I don't see a way Tnua can have a general backend implementation for them. It can't read nor write the velocity, because it's going to be in a custom component. Similarly, ground detection requires knowledge of the ground's physical shape - something which will be different in each game's in-house physics engine implementation.

So what can be done in order for these games to still enjoy Tnua? I can think of three options:

  1. These games can just implement the physics layer themselves. Its not that hard - the current source files that implement these for the various supported backends range between 318 LOC (for XBPD 2D) to 333 LOC (for Rapier 3D). Over a third of each implementation is dedicated to ground detection, and is a bit inflated because it needs to handle multiple configurations (ray vs shape casing, with or without ghost platforms detection). A custom implementation that only needs to handle one configuration should be easier - though I'd wager the ground detection will still be the most complex part.
  2. Tnua can have its own basic physics engine implementation, and then interact with it. I don't like this solution - it'd mean I'll have to maintain my own physics engine just for Tnua. That engine will have neither the power and refinement of Rapier and XPBD (I'm not going to make something of this caliber, and even if I would - wouldn't that miss the entire point of this feature request?), nor the flexibility of custom engine (because users won't be able to edit its code to their liking, and making it extensible enough is an endeavor of its own)
  3. If not an actual (although degraded) physics engine, Tnua could just define the components it needs from the physics engine, and the game can built its own physics based on these components. It's better than Tnua making a full engine, but still restrictive since the game has less control over the layout.

The first solution is something that can already be done today. As for the second and third - I don't want Tnua to be responsible for such things, but if someone makes them (in case of the second solution, that would just be another physics engine) I see no issue with having Tnua support it officially (with a different crate, but still under this repository)

dror-g commented 10 months ago

Thanks for the detailed reply! very interesting. I see your point on needing Newtonian information on the character and ground detection / geometry.

I did think about storing object velocity in a custom component, with a system to "teleport" objects each frame, but didn't realise it would be an issue for Tnua to read the velocities as you rightly pointed out.

So option 1 - implementing a physics layer - does sound like the best option. Personally, I'll probably attempt to use Parry3d for collision detection/prevention in such a backend.

That might be a valid approach for a "generic" backend in Tnua as in option 3, with Parry handling collisions, and ground detection provided by Tnua, and Tnua will define and require a velocity component (and a motor method that "teleports" objects rather than applying force). That doesn't sound as demanding as having a custom, degraded physics engine built into Tnua, but it will be a completely separate track for development, as simple (or not) as it may be..

Or perhaps Rapier KinematicCharacterController could be used. Again, the actual moving of the object will be done manually, but Tnua could help with animation and state if it's used in a simple physics backed as described above..

Thanks again for a great crate, detailed answer, and links to all the relevant code & docs!

idanarye commented 10 months ago

Not sure what you mean by "teleport", but if the games physics has velocity and gravity then Tnua will have to be able to modify that velocity. Otherwise the vertical velocity will keep accumulating gravity until the entity becomes so fast the teleport can no longer fix it in a single frame before it hits the ground.

Also - this sounds like something that's gonna jitter quite a lot.

Or perhaps Rapier KinematicCharacterController could be used.

When they introduced KinematicCharacterController I tried to make Tnua use it, and it did not work very well. Maybe I did it wrong (I did try to imitate the whole floating thing but instead of using the raycast use the kinematic controller's offset feature), but I've seen in Discord that other people are also struggling with it, so maybe it was not fully baked yet (still?)

But either way, wouldn't this require Rapier? And if you already have Rapier - why not use a dynamic character controller?

dror-g commented 10 months ago

Sorry, by teleport I meant moving the character by directly altering its transform rather than applying forces. Unity term I think. And yes it does tend to jitter, and if some objects use physics and others are moved by transform alterations it causes explosive results (in Unity at least).

For me, the reason for kinematic rapier or not using physics at all, is performance. On mobile devices Bevy struggles with 100..+200 plus dynamic entities, depending on device of course, My laptop can handle almost 1000.

It's such a shame to "waste" the capabilities of ECS systems on such a low entity count, especially in simple games like mine, where all I wanted was collision detection and movement.

I'm using XPBD atm, perhaps Rapier will be faster, but physics was difficult in Unity DOTS as well, so that's why I'm looking for simpler solutions.

dror-g commented 10 months ago

Switched to Rapier - it's so much faster. 1000 colliding objects with ease.

Kept this issue open thinking I'll attempt to implement simple pseudo-physics, but I think it's not necessary. at least for me.

Thanks again for your help Idan! hope to bother you on Yoleck soon ;)

idanarye commented 10 months ago

I don't know if implementing your own pseudo-physics will really be faster. I doubt the benefit of doing a less elaborate simulation can outweigh the collision graph optimization that Rapier does.

dror-g commented 10 months ago

That's probably true.
Perhaps if I kept Parry it wouldn't be that bad?