character_controller_setup
There are two ways to use the character-controller with bevy_rapier
: using the KinematicCharacterController
component
or using the RapierContext::move_shape
method. The component approach is more convenient, but the move_shape
approach
can be slightly more flexible in terms of filtering.
Refer to the API documentation of RapierContext::move_shape
for details on how to use it.
The KinematicCharacterController
component must be added to the same entity as a TransformBundle
bundle. If the field
KinematicCharacterController::custom_shape
isn’t set, then the entity it is attached to must also contain a Collider
component.
That collider can optionally be attached to a rigid-body. At each frame, the KinematicCharacterController::translation
field can be set to the desired translation for that character.
During the next physics update step, that translation will be resolved against obstacles, and the resulting movement will be automatically applied to the entity’s transform, or the transform of the entity containing the rigid-body the collider to move is attached to.
The applied character motion, and the information of whether the character
is touching the ground at its final position, can be read with the KinematicCharacterControllerOutput
component
(inserted automatically to the same entity as the KinematicCharacterController
component).
- Example 2D
- Example 3D
fn setup_physics(mut commands: Commands) {
commands
.spawn(RigidBody::KinematicPositionBased)
.insert(Collider::ball(0.5))
.insert(KinematicCharacterController::default());
}
fn update_system(mut controllers: Query<&mut KinematicCharacterController>) {
for mut controller in controllers.iter_mut() {
controller.translation = Some(Vec2::new(1.0, -0.5));
}
}
fn read_result_system(controllers: Query<(Entity, &KinematicCharacterControllerOutput)>) {
for (entity, output) in controllers.iter() {
println!(
"Entity {:?} moved by {:?} and touches the ground: {:?}",
entity, output.effective_translation, output.grounded
);
}
}
fn setup_physics(mut commands: Commands) {
commands
.spawn(RigidBody::KinematicPositionBased)
.insert(Collider::ball(0.5))
.insert(SpatialBundle::default())
.insert(KinematicCharacterController {
..KinematicCharacterController::default()
});
}
fn update_system(time: Res<Time>, mut controllers: Query<&mut KinematicCharacterController>) {
for mut controller in controllers.iter_mut() {
controller.translation = Some(Vec3::new(1.0, -5.0, -1.0) * time.delta_seconds());
}
}
fn read_result_system(controllers: Query<(Entity, &KinematicCharacterControllerOutput)>) {
for (entity, output) in controllers.iter() {
println!(
"Entity {:?} moved by {:?} and touches the ground: {:?}",
entity, output.effective_translation, output.grounded
);
}
}
The character’s shape may be any shape supported by Rapier. However, it is recommended to either use a cuboid, a ball, or a capsule since they involve less computations and less numerical approximations.
The built-in character controller does not support rotational movement. It only supports translations.