bevy_rapier: Bevy parent transform is not used
Currently bevy_rapier3d uses Transform component to read entity absolute transform. But this component is a transform relative to a parent in Bevy world. On the other hand GlobalTransform is an absolute transform for entity. Because of this if there is an entity with non-identity transform and as a children of it is another entity with a collider, collisions will not be detected in the real object location. For example when running following code ball collider will be placed at 0,0,0 instead of 0,10,0:
commands.spawn_bundle((
Transform::from_xyz(0.0, 10.0, 0.0),
GlobalTransform::default(),
))
.with_children(|parent| {
parent
.spawn_bundle((
Transform::default(),
GlobalTransform::default(),
))
.insert(RigidBody::Fixed)
.insert(Collider::ball(1.0));
});
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 7
- Comments: 31 (23 by maintainers)
Commits related to this issue
- update: add child sensor collider to tower This sensor will be used to determine the attack range of the tower. NOTE: discovered that the collider doesn't use the global transform to stay in sync. M... — committed to quackercrumbs/tower-defense by quackercrumbs 2 years ago
- update: add child sensor collider to tower This sensor will be used to determine the attack range of the tower. NOTE: discovered that the collider doesn't use the global transform to stay in sync. M... — committed to quackercrumbs/tower-defense by quackercrumbs 2 years ago
- Use GlobalTransform, closes #172 — committed to gardum-game/bevy_rapier by Shatur 2 years ago
- Use GlobalTransform, closes #172 — committed to gardum-game/bevy_rapier by Shatur 2 years ago
- Use GlobalTransform, closes #172 — committed to gardum-game/bevy_rapier by Shatur 2 years ago
Thanks for fast resolution! I really appreciate it!
@Shatur I’ll probably make a release of Rapier first next week. I’ll make a new release of
bevy_rapierafter.To me it looks like the docs says that the
GlobalTransformis updated in thetransform_propagate_systemsystem, but it doesn’t states that theGlobalTransformmust not be updated/modified elsewhere. If it mustn’t be modified otherwise, the docs should be more explicit about it. Something like “GlobalTransform is updated exclusively by […]”.So, here is my though: we need a solution as soon as possible, and we know (thanks to
heron) that callingtransform_propagate_systemis simple does work well with the current way Bevy works. So let’s make this modification. Best-case scenario,GlobalTransformnever changes, and we benefit from any futuretransform_propagate_systemparallelism performance improvements if there are any for “free”.We also know thanks to @maniwani that this may not be a perfect long-term solution (e.g. we are screwed if all its fields are merged into a single affine matrix), so we should keep our minds open to alternatives. I’m not sure I like adding another
GlobalPhysicsTransformcomponent used instead ofGlobalTransformbecause that would be yet another transform component that the user needs to be added to the whole hierarchy. So ideally we should see if we could manage to avoid a new component (by keeping the current transform in local memory while recurring, and by making sure we don’t need to read that transform twice) but that would take time to design.@Shatur Looks like heron simply runs a second transform propagation: https://github.com/jcornaz/heron/blob/main/rapier/src/lib.rs#L107 I think we should do something similar, at least as a stopgap solution until we get more feedback on the limitations of this approach.
I am not a big fan of the suggestions where Rapier implements its own transform hierarchy since that was one of the main pain point in previous versions of
bevy_rapier.