Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Transform for moving and positioning bodies #96

Merged
merged 5 commits into from
Jul 29, 2023

Conversation

Jondolf
Copy link
Owner

@Jondolf Jondolf commented Jul 25, 2023

Currently, the only way to move and position bodies after initialization is to use the Position and Rotation components. Using these separate components has many benefits over using Transform for physics, as discussed in #16.

However, if we want Bevy XPBD to feel as integrated into Bevy as possible, it would make sense to allow using Transform directly for moving bodies, as it is what Bevy and the rest of its ecosystem typically uses. This would also allow third party crates to move bodies in a more backend-agnostic way without having to have explicit support for Bevy XPBD.

This PR adds a new synchronization system for SyncPlugin that updates Position and Rotation based on changes in GlobalTransform. This does not replace the separate components, but rather adds another way to position bodies in a more familiar and native way.

The new behaviour is entirely optional, and there is a new SyncConfig resource for disabling syncing features.

Caveats

Transform changes are only handled if they happen before physics (fixed)

Update: I fixed this by changing the GlobalTransform change detection a bit and running transform propagation before and after each physics frame. Transforms can now be modified at any time, and everything should work normally. The problem described below no longer applies.

To only detect user changes in GlobalTransform, I use a PreviousGlobalTransform component that stores the global transform from the very beginning of each frame. If the transform has changed before physics is run, transform_to_position is run.

This avoids unnecessary runs of the system and circumvents some change detection problems, but it also means that Transform updates are only handled if they happen before physics is run.

Additional transform propagation

To handle hierarchies and to have GlobalTransform change detection working properly, I need to run a total of three copies of Bevy's transform propagation: one before physics, one right after physics, and a final one after position_to_transform syncing.

I don't think it's particularly expensive, but it would be nice to find a way to avoid running it so many times. However, I'm not sure if it's avoidable if we want to handle the Transform syncing in a robust manner.

Best practices for positioning bodies

There are now two ways to position bodies, either using Transform or using Position and Rotation. The best practises are unclear here; should people use transforms, which is considered to be a more native way, or should they continue to use Position and Rotation, which is what the engine itself uses?

For now, I think it's enough to just mention both ways in the docs and let people make their own conclusions. Later on, we can maybe make clearer recommendations, and maybe even revisit #16 in some capacity.

`Tranform` can now be used directly to move bodies.
There seems to be a small occasional jittery
delay though.
@Jondolf Jondolf added the C-Enhancement New feature or request label Jul 25, 2023
@Elabajaba
Copy link

Would this also add support for scaling colliders using bevy's Transform?

@Jondolf
Copy link
Owner Author

Jondolf commented Jul 28, 2023

Not yet, but I will soon add some Scale or ColliderScale component that syncs with Transform scale (so you could just use Transform directly).

I could maybe use Transform for scale internally as well, but if I already have Position and Rotation, I think it would make sense to have Scale, and it would also allow f64 (although it's quite unnecessary for scale itself).

Previously, only `Transform` updates that happened before
the physics frame were detected and handled.

Now `Transform` can be changed at any moment, and it should act the
same as changing `Position`/`Rotation`.

`Transform` updates that happen during the physics frame also don't
override the `Position` update, so gravity and constraints are applied
normally even when constantly
changing the translation.

This requires some extra transform propagation and other computations,
but it shouldn't be that expensive and I believe it's worth it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants