character_controller_setup
The character controller implementation is exposed as the KinematicCharacterController class. This class only
contains information about the character controller’s behavior. It does not contain any collider-specific or
rigid-body-specific information like handles, velocities, positions, etc. Therefore, the same instance of
KinematicCharacterController can be used to control multiple rigid-bodies/colliders if they rely on the same set of
parameters. Its settings (detailed in the next sections) are properties that can also be given as keyword arguments
to its constructor (e.g. KinematicCharacterController(slide=False, max_slope_climb_angle=0.5)). The
KinematicCharacterController exposes only two methods:
move_shapeis responsible for calculating the possible movement of a character based on the desired movement, obstacles, and character controller options. It is given the timestep length, the rigid-body set and the collider set (both unused and kept for backward compatibility: they can beNone, or must be the sets of the query pipeline), the query pipeline of the world containing the obstacles (e.g.world.query_pipeline), the shape of the character (aSharedShape, e.g. theshapeof itsCollider), its current pose, the desired translation, and optionally theQueryFilterselecting the obstacles (see the filtering section) and a callback receiving the collisions (see the collisions section).solve_character_collision_impulsesis detailed in the collisions section.
# The translation we would like to apply if there were no obstacles.
desired_translation = (1.0, -2.0, 3.0)
# Create the character controller, here with the default configuration.
character_controller = rp.KinematicCharacterController()
# Make sure the character we are trying to move isn’t considered an obstacle.
query_filter = rp.QueryFilter().exclude_rigid_body(rigid_body_handle)
# Calculate the possible movement.
corrected_movement = character_controller.move_shape(
dt, # The timestep length (can be set to world.integration_parameters.dt).
None, # The rigid-body set, unused: the one of the query pipeline is used.
None, # The collider set, unused: the one of the query pipeline is used.
world.query_pipeline, # The query pipeline containing the obstacles.
character_shape, # The character’s shape.
character_pos, # The character’s initial position.
desired_translation,
query_filter, # The obstacles to consider.
)
# TODO: apply the `corrected_movement.translation` to the rigid-body or collider based on the rules described below.
The obstacles are taken at the positions they had at the end of the last PhysicsWorld.step (or the last
PhysicsWorld.update_query_pipeline). The returned EffectiveCharacterMovement contains the corrected movement (its
translation property), as well as whether the character touches the ground at its final position (its grounded
property), and whether it is sliding down a slope that is too steep to climb (its is_sliding_down_slope property).
The corrected movement isn’t applied automatically: the recommended way to update the character’s position depends on
its representation:
- A collider not attached to any rigid-body: set the collider’s position directly (with its
translationproperty) to the corrected movement added to its current position. - A velocity-based kinematic rigid-body: set its velocity (with its
linvelproperty) to the computed movement divided by the timestep length. - A position-based kinematic rigid-body: set its next kinematic position (with
RigidBody.set_next_kinematic_translation) to the corrected movement added to its current position.
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.