Expand description
§Tnua - A Character Controller for Bevy.
Tnua (“motion” in Hebrew) is a floating character controller, which means that instead of constantly touching the ground the character floats above it, which makes many aspects of the motion control simpler.
Tnua can use Rapier or Avian, and supports both the 2D and 3D versions of both with integration crates:
- For Rapier 2D, add the bevy-tnua-rapier2d crate.
- For Rapier 3D, add the bevy-tnua-rapier3d crate.
- For Avian 2D, add the bevy-tnua-avian2d crate.
- For Avian 3D, add the bevy-tnua-avian3d crate.
- Third party integration crates. Such crates should depend on bevy-tnua-physics-integration-layer and not the main bevy-tnua crate.
Each physics integration crate has basic usage instructions for adding it in its documentation.
When using a physics backend with double precision (like Avian with the f64
flag), the f64
flag should be added to all the Tnua crates. This applies to double precision data that gets
defined by the physics backend - Bevy itself will still use single precision, and this is the
precision the position and rotation will use.
In addition to the physics integration plugin, the
TnuaControllerPlugin
should also be added.
Some physics backends support running in different schedules (e.g. FixedUpdate
to make the
simulation deterministic). When using this feature, the physics integration plugin,
TnuaControllerPlugin
, and any other Tnua plugin that supports it (such as
TnuaCrouchEnforcer
) must also be registered in
that schedule, using their ::new()
method instead of ::default()
. The player controls
systems must also be registered under that same schedule (instead of under Update
, which is
where it should usually be registered)
A Tnua controlled character must have a dynamic rigid body, everything from
Tnua<physics-backend>IOBundle
(e.g. - for Rapier 3D, use TnuaRapier3dIOBundle
), and a
TnuaController
(and its automatically added required component):
cmd.insert(RigidBody::Dynamic);
cmd.insert(TnuaRapier3dIOBundle::default()); // this one depends on the physics backend
cmd.insert(TnuaController::default());
Typically though it’d also include a Collider
.
§Optional But Recommended
- Tnua, by default, casts a single ray to the ground. This can be a problem when the character
stands on a ledge, because the ray may be past the ledge while the character’s collider
isn’t. To avoid that, use
Tnua<physics-backend>SensorShape
(e.g. - for Rapier 3D, useTnuaRapier3dSensorShape
) to replace the ray with a shape that resembles the collider. It is better to use a shape a little bit smaller than the collider, so that when the character presses against a wall Tnua won’t think it should be lifted up when the casted shape hits that wall. - Tnua will apply forces to keep the character upright, but it is also possible to lock
rotation so that there would be no tilting at all. This is done by Tnua itself - it has to be
done by the physics engine. Both Rapier and Avian can do it using a component called
LockedAxes
. When using it in 3D in combination of rotation controls (such asTnuaBuiltinWalk::desired_forward
) make sure to only lock the X and Z axess, so that Tnua could rotate the character around the Y axis.
§Controlling the Character
To control the character, update the TnuaController
by feeding it
a basis and zero or more actions. For some of the advanced features
to work, the system that does this needs to be placed inside the TnuaUserControlsSystemSet
system set.
fn player_control_system(mut query: Query<(
&mut TnuaController,
&PlayerInputComponent, // not part of Tnua - defined in user code
)>) {
for (mut controller, player_input) in query.iter_mut() {
controller.basis(TnuaBuiltinWalk {
// Move in the direction the player entered, at a speed of 10.0:
desired_velocity: player_input.direction_vector() * 10.0,
// Turn the character in the movement direction:
desired_forward: Dir3::new(player_input.direction_vector()).ok(),
// Must be larger than the height of the entity's center from the bottom of its
// collider, or else the character will not float and Tnua will not work properly:
float_height: 2.0,
// TnuaBuiltinWalk has many other fields that can be configured:
..Default::default()
});
if player_input.jump_pressed() {
// The jump action must be fed as long as the player holds the button.
controller.action(TnuaBuiltinJump {
// The full height of the jump, if the player does not release the button:
height: 4.0,
// TnuaBuiltinJump too has other fields that can be configured:
..Default::default()
});
}
}
}
Refer to the documentation of TnuaController
for more information,
but essentially the basis controls the general movement and the action is something
special (jump, dash, crouch, etc.)
§Motion Based Animation
TnuaController
can also be used to retreive data that can
be used to decide which animation to play. A useful helper for that is TnuaAnimatingState
.
Modules§
- builtins
- control_
helpers - Various helpers to make Tnua’s advanced features easier to use.
- controller
- data_
for_ backends - math
- obstacle_
radar - prelude
- radar_
lens - spatial_
ext - subservient_
sensors - util
Structs§
- Tnua
Action Context - Various data passed to
TnuaAction::apply
. - Tnua
Animating State - Utility for deciding which animation to play.
- Tnua
Basis Context - Various data passed to
TnuaBasis::apply
. - Tnua
Ghost Platform - A marker for jump/fall-through platforms.
- Tnua
Ghost Sensor - An addon for
TnuaProximitySensor
that allows it to detectTnuaGhostPlatform
colliders. - Tnua
Gravity - Change the gravity for a Tnua-controlled character.
- Tnua
Motor - Instructions on how to move forces to the rigid body.
- Tnua
NotPlatform - Marker component for colliders which Tnua should not treat as platform.
- Tnua
Obstacle Radar - Add this to a character entity to detect obstacles around it.
- Tnua
Proximity Sensor - Distance from another collider in a certain direction, and information on that collider.
- Tnua
Proximity Sensor Output - Information from
TnuaProximitySensor
that have detected another collider. - Tnua
Rigid Body Tracker - Newtonian state of the rigid body.
- Tnua
System Set - Umbrella system set for
TnuaPipelineStages
. - Tnua
User Controls System Set - The user controls should be applied in this system set.
- Tnua
VelChange - Represents a change to velocity (linear or angular)
Enums§
- Tnua
Action Initiation Directive - A decision by
TnuaAction::initiation_decision
that determines if the action can start. - Tnua
Action Lifecycle Directive - A decision by
TnuaAction::apply
that determines if the action should be continued or not. - Tnua
Action Lifecycle Status - Input for
TnuaAction::apply
that informs it about the long-term feeding of the input. - Tnua
Animating State Directive - Tnua
Pipeline Stages - The various stages of the Tnua pipeline.
- Tnua
Toggle - Allows disabling Tnua for a specific entity.
Traits§
- Dynamic
Action - Dynamic
Basis - Helper trait for accessing a basis and its trait with dynamic dispatch.
- Tnua
Action - A character movement command for performing special actions.
- Tnua
Basis - The main movement command of a character.