Skip to main content

rigid_body_position

The position of a rigid-body represents its location (translation) in 2D or 3D world-space, as well as its orientation (rotation). Its translational part is represented as a vector and its rotational part as an unit quaternion (in 3D) or a unit complex number (in 2D). Both are combined into a pose (the Pose type)Both are stored in the standard Bevy Transform componentIts translational part is represented as a vector (R3Vector) and its rotational part as a unit quaternion (R3Rotation) in 3D, or as an angle in radians (R2Rotation) in 2D. Both are combined into a pose (the R3Pose structure)Its translational part is represented as a vector (Vec3, though a tuple of three floats is accepted as well) and its rotational part as a unit quaternion (Rotation3). Both are combined into a pose (the Isometry3 type).

The position of a rigid-body can be set when creating it. It can also be set after its creation as illustrated below.

warning

Directly changing the position of a rigid-body is equivalent to teleporting it: this is a not a physically realistic action! Teleporting a dynamic or kinematic bodies may result in odd behaviors especially if it teleports into a space occupied by other objects. For dynamic bodies, forces, impulses, or velocity modification should be preferred. For kinematic bodies, see the discussion after the examples below.

/* Set the position when the rigid-body is created. */
let rigid_body = RigidBodyBuilder::dynamic()
// The rigid body translation.
// Default: zero vector.
.translation(Vector::new(0.0, 5.0))
// The rigid body rotation.
// Default: no rotation.
.rotation(5.0)
// The rigid body position. Will override `.translation(...)` and `.rotation(...)`.
// Default: the identity isometry.
.pose(Pose::new(Vector::new(1.0, 2.0), 0.4))
// All done, actually build the rigid-body.
.build();
/* Set the position after the rigid-body creation. */
let rigid_body = &mut world.bodies[rigid_body_handle];
// The `true` argument makes sure the rigid-body is awake.
rigid_body.set_translation(Vector::new(0.0, 5.0), true);
rigid_body.set_rotation(Rotation::new(0.2), true);
assert_eq!(rigid_body.translation(), Vector::new(0.0, 5.0));
assert_eq!(rigid_body.rotation().angle(), 0.2);

rigid_body.set_position(Pose::new(Vector::new(1.0, 2.0), 0.4), true);
assert_eq!(*rigid_body.position(), Pose::new(Vector::new(1.0, 2.0), 0.4));
commands
.spawn(RigidBody::Dynamic)
.insert(Transform::from_xyz(0.0, 5.0, 0.0))
/* Change the position inside of a system. */
fn modify_body_translation(mut positions: Query<&mut Transform, With<RigidBody>>) {
for mut position in positions.iter_mut() {
position.translation.y += 0.1;
}
}
/* Set the position when the rigid-body is created. */
let rigidBodyDesc = RAPIER.RigidBodyDesc.dynamic()
// The rigid body translation.
// Default: zero vector.
.setTranslation(0.0, 5.0)
// The rigid body rotation.
// Default: no rotation.
.setRotation(5.0);
let rigidBody = world.createRigidBody(rigidBodyDesc);
/* Set the position after the rigid-body creation. */
// The `true` argument makes sure the rigid-body is awake.
rigidBody.setTranslation({ x: 0.0, y: 5.0 }, true);
rigidBody.setRotation(0.2, true);
/* Set the position when the rigid-body is created. */
R2RigidBodyDesc rigid_body = r2DynamicRigidBodyDesc();
// The rigid body translation.
// Default: zero vector.
rigid_body.position.translation = r2Vector(0.0, 5.0);
// The rigid body rotation.
// Default: no rotation.
rigid_body.position.rotation = r2Rotation(5.0);
// The rigid body position. Will override the translation and rotation set above.
// Default: the identity pose.
rigid_body.position = r2Pose(r2Vector(1.0, 2.0), r2Rotation(0.4));
/* Set the position after the rigid-body creation. */
// The last `1` argument makes sure the rigid-body is awake.
r2RigidBody_SetTranslation(rigid_body_handle, r2Vector(0.0, 5.0), 1);
r2RigidBody_SetRotation(rigid_body_handle, r2Rotation(0.2), 1);
R2Vector translation = r2RigidBody_Translation(rigid_body_handle);
R2Rotation rotation = r2RigidBody_Rotation(rigid_body_handle);
assert(translation.x == 0.0 && translation.y == 5.0);
assert(rotation.angle == (R2Real)0.2);

r2RigidBody_SetPosition(rigid_body_handle, r2Pose(r2Vector(1.0, 2.0), r2Rotation(0.4)), 1);
R2Pose position = r2RigidBody_Position(rigid_body_handle);
assert(position.translation.x == 1.0 && position.translation.y == 2.0);
assert(position.rotation.angle == (R2Real)0.4);
# Set the position when the rigid-body is created.
rigid_body = (
rp.RigidBody.dynamic()
# The rigid body translation.
# Default: zero vector.
.translation((0.0, 5.0, 1.0))
# The rigid body rotation, as a scaled rotation axis.
# Default: no rotation.
.rotation((0.2, 0.0, 0.0))
# The rigid body position. Will override `.translation(...)` and `.rotation(...)`.
# Default: the identity isometry.
.position(rp.Isometry3((1.0, 2.0, 3.0), rp.Rotation3.from_scaled_axis((0.2, 0.0, 0.0))))
# All done, actually build the rigid-body.
.build()
)
# Set the position after the rigid-body creation.
rigid_body = world.rigid_bodies[rigid_body_handle]
# Setting these properties automatically wakes the rigid-body up.
rigid_body.translation = (0.0, 5.0, 1.0)
rigid_body.rotation = rp.Rotation3.from_scaled_axis((0.2, 0.0, 0.0))
assert rigid_body.translation == rp.Vec3(0.0, 5.0, 1.0)
assert rigid_body.rotation.scaled_axis == rp.Vec3(0.2, 0.0, 0.0)

rigid_body.position = rp.Isometry3((1.0, 2.0, 3.0), rp.Rotation3.from_scaled_axis((0.0, 0.4, 0.0)))
assert rigid_body.position == rp.Isometry3(
(1.0, 2.0, 3.0), rp.Rotation3.from_scaled_axis((0.0, 0.4, 0.0))
)

In order to move a dynamic rigid-body it is strongly discouraged to set its position directly as it may results in weird behaviors: it's as if the rigid-body teleports itself, which is a non-physical behavior. For dynamic bodies, it is recommended to either set its velocity or to apply forces or impulses.

For velocity-based kinematic bodies, it is recommended to set its velocity instead of setting its position directly. For position-based kinematic bodies, it is recommended to use the special methods:

  • RigidBody::set_next_kinematic_rotation
  • RigidBody::set_next_kinematic_translation

These methods will let the physics pipeline compute the fictitious velocity of the position-based kinematic body for more realistic interactions with other rigid-bodies. These methods won't immediately modify the position of the kinematic body itself. The position of the kinematic body will be automatically set to these values during the next physics pipeline update.

For velocity-based kinematic bodies, it is recommended to set its velocity instead of setting its position directly. For position-based kinematic bodies, it is recommended to modify its Transform (changing its velocity won’t have any effect). This won't teleport the kinematic body immediately: the modified Transform is used as its next kinematic position, which lets the physics engine compute the fictitious velocity of the kinematic body for more realistic interactions with other rigid-bodies.

For velocity-based kinematic bodies, it is recommended to set its velocity instead of setting its position directly. For position-based kinematic bodies, it is recommended to use the special methods:

  • RigidBody.setNextKinematicRotation
  • RigidBody.setNextKinematicTranslation

These methods will let the physics pipeline compute the fictitious velocity of the position-based kinematic body for more realistic interactions with other rigid-bodies. These methods won't immediately modify the position of the kinematic body itself. The position of the kinematic body will be automatically set to these values during the next physics pipeline update.

For velocity-based kinematic bodies, it is recommended to set its velocity instead of setting its position directly. For position-based kinematic bodies, it is recommended to use the special functions:

  • r3RigidBody_SetNextKinematicRotation
  • r3RigidBody_SetNextKinematicTranslation
  • r3RigidBody_SetNextKinematicPosition (for both at once)

These functions will let the physics pipeline compute the fictitious velocity of the position-based kinematic body for more realistic interactions with other rigid-bodies. These functions won't immediately modify the position of the kinematic body itself. The position of the kinematic body will be automatically set to these values during the next physics pipeline update (the pending pose can be read with r3RigidBody_NextPosition).

For velocity-based kinematic bodies, it is recommended to set its velocity instead of setting its position directly. For position-based kinematic bodies, it is recommended to use the special methods:

  • RigidBody.set_next_kinematic_rotation
  • RigidBody.set_next_kinematic_translation
  • RigidBody.set_next_kinematic_position (for both at once)

These methods will let the physics pipeline compute the fictitious velocity of the position-based kinematic body for more realistic interactions with other rigid-bodies. These methods won't immediately modify the position of the kinematic body itself. The position of the kinematic body will be automatically set to these values during the next physics pipeline update (the pending pose can be read with the RigidBody.next_position property).

platform_handle = world.add_body(rp.RigidBody.kinematic_position_based(translation=(0.0, 1.0, 0.0)))
platform = world.rigid_bodies[platform_handle]

# Move the platform up by 0.01 at each step.
for _ in range(10):
next_translation = platform.translation + rp.Vec3(0.0, 0.01, 0.0)
platform.set_next_kinematic_translation(next_translation)
# The position isn't modified until the next step.
assert platform.next_position.translation == next_translation
world.step()