#[derive(TnuaScheme)]
{
// Attributes available to this derive:
#[scheme]
}
Expand description
Make an enum a control scheme for a Tnua character controller.
This implements the TnuaScheme trait for the enum, and also generates the following structs
required for implementing it (replace {name} with the name of the control scheme enum):
{name}Config- a struct with the configuration of the basis and all the actions.{name}ActionDiscriminant- an enum mirroring the control scheme, except all the variants are units.{name}ActionState- an enum mirroring the control scheme, except instead of just the input types each variant contains aTnuaActionStatewhich holds the input, configuration and memory of the action.
The enum itself must have a #[scheme(basis = ...)] attribute that specifies the basis of
the control scheme (typically TnuaBuiltinWalk). The following additional parameters are
allowed on that scheme attribute on the enum:
#[scheme(serde)]- derive Serialize and Deserialize on the generated action state enum.- This is mostly useful with (and will probably fail without) the
serializefeature enabled on the bevy-tnua crate. - The control scheme enum itself will not get these derives automatically - that derive will need to be added manually.
- With these, and with the
serializefeature enabled, theTnuaControllerandTnuaGhostOverwritesof the control scheme will also be serializable and deserializable - allowing networking libraries to synchronize them between machines. - Even without this setting and without the
serializefeature on the bevy-tnua crate, the generated configuration struct and the action discriminant enum will still get these derives.
- This is mostly useful with (and will probably fail without) the
#[scheme(config_ext = ...)]- add an extension field to the configuration struct generated for the control scheme. The field will have the nameextand the type specified by this parameter. This allows adding user-defined settings that the user control systems can utilize for character control related decisions (e.g. - max number of air actions allowed), and load these settings from the same asset.
Each variant must be a tuple variant, where the first element of the tuple is the action, followed by zero or more payloads.
Payloads are ignored by Tnua itself - they are for the user systems to keep track of data
related to the actions - except when they are annotated by #[scheme(modify_basis_config)].
Such payloads will modify the configuration when the action they are part of is in effect.
A variant may have a #[scheme(...)] attribute, supporting the following parameters:
#[scheme(same_trigger(OtherAction)]- whenOtherActionis one of the other action variants (which must not have asame_triggerof its own). This will get both actions (as well as any other action annotated with the samesame_trigger) to share a slot in Tnua’s feeding mechanism - which means that if one action is fed, all the others are treated as if alredy fed. Use this for actions that share a button - for example, a regular jump and a wall-jump. Without this mechanism, if the player holds the jump button and jumps toward a wall, the moment the user control system detects that the conditions for a wall-jump are met it’ll send the wall-jump action - and since that action was not fed that frame, Tnua will consider it a new action (“just pressed”) and immediately invoke the wall-jump. But if the wall-jump hassame_triggeras the jump - Tnua will see that the jump action is still being fed (even if the action itself is over) and thus the wall-jump will also be considered “already fed” and won’t trigger until the player releases and re-presses the button.
Example:
#[derive(TnuaScheme)]
#[scheme(basis = TnuaBuiltinWalk)]
pub enum ControlScheme {
Jump(TnuaBuiltinJump),
Crouch(
TnuaBuiltinCrouch,
// While this action is in effect, `SlowDownWhileCrouching` will change the
// `TnuaBuiltinWalkConfig` to reduce character speed.
#[scheme(modify_basis_config)] SlowDownWhileCrouching,
),
WallSlide(
TnuaBuiltinWallSlide,
// This payload has is ignored by Tnua, but user code can use it to tell which wall
// the character is sliding on.
Entity,
),
// The wall-jump uses the same button as the jump, so we annotate them with `same_trigger`.
#[scheme(same_trigger(Jump))]
// Wall-jump also uses `TnuaBuiltinJump`, but it's a separate variant so that it can have
// its own configuration and so that systems that introspect the current action can tell
// the difference - e.g. the animating system can play a different animation.
WallJump(TnuaBuiltinJump)
}