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 must also be registered in
that schedule, using their ::new() method instead of ::default().
§Defining the control scheme
The range of movement actions available to the character controller is defined by the control
scheme. The controle scheme is an enum that derives TnuaScheme. It needs to use an
attribute to define the basis - a constant mode of movement that character is always going to
be in. Simple games prboably want to use TnuaBuiltinWalk,
which defines a simple floating character that can be moved around with a simple vector and can
be told to face a direcetion.
The enum’s variants define the actions - various movement commands on top of the basis, like jumping, crouching, climbing, etc. The variants need to be tuple variants, with the action’s type as the first tuple member of each variants.
#[derive(TnuaScheme)]
#[scheme(basis = TnuaBuiltinWalk)]
enum ControlScheme {
Jump(TnuaBuiltinJump),
// more actions can be defined as more variants
}For more avaialbe attributes, see the TnuaScheme derive macro
documentation
§Spawning the character controller
A Tnua controlled character must have a dynamic rigid body, a TnuaConfig. The controller is
parameterized by the control scheme and needs a configuration (based on the control scheme) as
an asset handle:
cmd.insert(RigidBody::Dynamic);
cmd.insert(TnuaController::<ControlScheme>::default());
cmd.insert(TnuaConfig::<ControlScheme>(
// This example creates the configuration by code and injects it to the Assets resource,
// but a proper game will probably want to load it from an asset file.
control_scheme_configs.add(ControlSchemeConfig {
// The basis' configuration is alwayts named `basis`:
basis: TnuaBuiltinWalkConfig {
// 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,
// TnuaBuiltinWalkConfig has many other fields that can be configured:
..Default::default()
},
// Actions' configurations are named after the variants defining the actions:
jump: TnuaBuiltinJumpConfig {
// The full height of the jump, if the player does not release the button:
height: 4.0,
// TnuaBuiltinJumpConfig too has other fields that can be configured:
..Default::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 TnuaUserControlsSystems system set.
fn player_control_system(mut query: Query<(
&mut TnuaController<ControlScheme>,
&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:
desired_motion: player_input.direction_vector(),
// Turn the character in the movement direction:
desired_forward: Dir3::new(player_input.direction_vector()).ok(),
};
if player_input.jump_pressed() {
// The jump action must be fed as long as the player holds the button.
controller.action(ControlScheme::Jump(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.
Re-exports§
pub use controller::TnuaConfig;pub use controller::TnuaController;pub use controller::TnuaControllerPlugin;pub use ghost_overrides::TnuaGhostOverwrites;pub use sensor_sets::TnuaSensorsEntities;
Modules§
- action_
state - basis_
capabilities - Generic properties of basis that actions and control helpers may rely on.
- builtins
- control_
helpers - Various helpers to make Tnua’s advanced features easier to use.
- controller
- data_
for_ backends - ghost_
overrides - math
- obstacle_
radar - prelude
- radar_
lens - sensor_
sets - spatial_
ext - util
Structs§
- Tnua
Action Context - Various data passed to
TnuaAction::apply. - Tnua
Animating State - Utility for deciding which animation to play.
- Tnua
Basis Access - References to the full state of the basis in the controller.
- 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
TnuaProximitySensorthat allows it to detectTnuaGhostPlatformcolliders. - 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
TnuaProximitySensorthat have detected another collider. - Tnua
Rigid Body Tracker - Newtonian state of the rigid body.
- Tnua
Sensor Of - Tnua
Sensors Set - Tnua
Systems - Umbrella system set for
TnuaPipelineSystems. - Tnua
User Controls Systems - 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_decisionthat determines if the action can start. - Tnua
Action Lifecycle Directive - A decision by
TnuaAction::applythat determines if the action should be continued or not. - Tnua
Action Lifecycle Status - Input for
TnuaAction::applythat informs it about the long-term feeding of the input. - Tnua
Animating State Directive - Tnua
Pipeline Systems - The various stages of the Tnua pipeline.
- Tnua
Toggle - Allows disabling Tnua for a specific entity.
Traits§
- Tnua
Action - A character movement command for performing special actions.
- Tnua
Action Discriminant - An enum with a unit variant for each variant of the control scheme.
- Tnua
Action State - An enum mirroring the control scheme, except instead of just having the input of each action
each variant has a
TnuaActionStatewhich contains the action’s input, configuration and memoery. If the variant in the control scheme has payload, they are copied to the variant in action state as is. - Tnua
Basis - The main movement command of a character.
- Tnua
Config Modifier - Implement on payloads that can modify the configuration while the relevant action is running.
- Tnua
Scheme - See the derive macro.
- Tnua
Scheme Config - A big configuration struct, containing the configuration of the basis and of all the actions of a control scheme.
Derive Macros§
- Tnua
Scheme - Make an enum a control scheme for a Tnua character controller.