Expand description
§Physics Integration Layer for bevy-tnua
Crates that implement a physics layer integration for Tnua (like bevy-tnua-rapier or bevy-tnua-avian) should depend on this crate and not on the main bevy-tnua crate. This crate should update less often - only when there are changes in the integration layer (which is not supposed to change as much) or when Bevy itself updates.
To integrate a Bevy physics engine with Tnua, one should create a plugin named
Tnua<physics-engine-name>Plugin
, which:
-
Configures
TnuaSystemSet
to not run when the physics engine is paused. -
Add systems, to the
TnuaPipelineStages::Sensors
stage, that update:TnuaRigidBodyTracker
with the objects current kinematic status (position, rotation, velocity, angular velocity) as well as the gravity currently applied to it.TnuaProximitySensor
with the first tangible collider within range, andTnuaGhostSensor
with all the ghost colliders found before that tangible collider.- A tangible collider is a non-ghost collider that physically interacts with the character’s collider.
- A ghost collider is a collider marked with the
TnuaGhostPlatform
component. It may or may not physically interact with the character’s collider - as long as it has the component it is considered a ghost collider. - The sensor should ignore the owner entity’s collider.
- If the sensor has the
TnuaSubservientSensor
component, the “owner entity” is defined as theowner_entity
field from that component and not the entity the sensor component is attached to. - The detection should be done with a ray cast, unless the sensor is configured to cast a
shape instead. Such configuration is done with component, defined by the integration
crate, that specifies the shape to cast in a way the integration crate can pass on to the
physics engine. The name of that component should be
Tnua<physics-engine-name>SensorShape
.
The integration crate may update all these components in one system or multiple systems as it sees fit.
-
Add a system, to the
TnuaPipelineStages::Motors
stage, that applies all the impulses and accelerations fromTnuaMotor
components.Here, too, if it makes sense to split this work into multiple systems the integration crate may do so at its own discretion.
-
Ensure that
TnuaSystemSet
runs before the integration backend’s systems.
The integration backend’s systems must run with the same timing as the physics backend. If the
physics backend supports running in a different schedule, the integration plugin should also
support it by adding a ::new()
method that accepts a schedule and registers all the systems
there. It should also implement Default
to make it run in the default schedule (usually
Update
)
Note that a physics backend may run its systems under PostUpdate
instead of Update
(both
Rapier and Avian do this by default). In this case, it’s still okay for the integration backend
to run under Update
, because they use the same timing.
If the integration crate needs the character entity to have more components from the physics
engine crate, that one would not naturally add to it, it should define a bundle named
Tnua<physics-engine-name>IOBundle
that adds these components. One would naturally add a rigid
body and a collider, so they should not go in that bundle, but if the crate needs things users
rarely think about - for example, bevy_rapier’s ReadMassProperties
- then these components
should go in that bundle.
Modules§
Structs§
- Umbrella system set for
TnuaPipelineStages
.
Enums§
- The various stages of the Tnua pipeline.