Crate bevy_tnua

Crate bevy_tnua 

Source
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:

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.

  • 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, use TnuaRapier3dSensorShape) 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 as TnuaBuiltinWalk::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§

TnuaActionContext
Various data passed to TnuaAction::apply.
TnuaAnimatingState
Utility for deciding which animation to play.
TnuaBasisAccess
References to the full state of the basis in the controller.
TnuaBasisContext
Various data passed to TnuaBasis::apply.
TnuaGhostPlatform
A marker for jump/fall-through platforms.
TnuaGhostSensor
An addon for TnuaProximitySensor that allows it to detect TnuaGhostPlatform colliders.
TnuaGravity
Change the gravity for a Tnua-controlled character.
TnuaMotor
Instructions on how to move forces to the rigid body.
TnuaNotPlatform
Marker component for colliders which Tnua should not treat as platform.
TnuaObstacleRadar
Add this to a character entity to detect obstacles around it.
TnuaProximitySensor
Distance from another collider in a certain direction, and information on that collider.
TnuaProximitySensorOutput
Information from TnuaProximitySensor that have detected another collider.
TnuaRigidBodyTracker
Newtonian state of the rigid body.
TnuaSensorOf
TnuaSensorsSet
TnuaSystems
Umbrella system set for TnuaPipelineSystems.
TnuaUserControlsSystems
The user controls should be applied in this system set.
TnuaVelChange
Represents a change to velocity (linear or angular)

Enums§

TnuaActionInitiationDirective
A decision by TnuaAction::initiation_decision that determines if the action can start.
TnuaActionLifecycleDirective
A decision by TnuaAction::apply that determines if the action should be continued or not.
TnuaActionLifecycleStatus
Input for TnuaAction::apply that informs it about the long-term feeding of the input.
TnuaAnimatingStateDirective
TnuaPipelineSystems
The various stages of the Tnua pipeline.
TnuaToggle
Allows disabling Tnua for a specific entity.

Traits§

TnuaAction
A character movement command for performing special actions.
TnuaActionDiscriminant
An enum with a unit variant for each variant of the control scheme.
TnuaActionState
An enum mirroring the control scheme, except instead of just having the input of each action each variant has a TnuaActionState which 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.
TnuaBasis
The main movement command of a character.
TnuaConfigModifier
Implement on payloads that can modify the configuration while the relevant action is running.
TnuaScheme
See the derive macro.
TnuaSchemeConfig
A big configuration struct, containing the configuration of the basis and of all the actions of a control scheme.

Derive Macros§

TnuaScheme
Make an enum a control scheme for a Tnua character controller.