Skip to main content

Debug-renderer

Rapier is a physics engine, it doesn't render anything. What is displayed by your application comes from your own renderer, and game assets generally don’t match the shapes seen by the physics engine exactly. Therefore a collider given the wrong size, a joint attached at the wrong place, or a rigid-body that is not where its sprite is, can be difficult to debug (and easy to misinterpret as physics-engine-bugs).

To help with debugging physics, Rapier’s debug-renderer exists to convert the content of the physics scene into a set of colored lines that your application to obtain a wireframe view of what Rapier actually sees.

info

The debug-renderer is behind the debug-render-2d and debug-render-3d cargo features (the one matching the dimension of the crate is enabled by default, and can also be enabled with the debug-render alias). The rapier-debug-render feature enables the debug-render pipeline of Rapier alone, without any Bevy rendering dependency, in case you want to implement your own DebugRenderBackend.

The debug-renderer is enabled by adding the RapierDebugRenderPlugin to your app. It draws the lines with the gizmos of Bevy, after the propagation of the transforms, for every physics context. The plugin is also where the initial DebugRenderStyle (the colors and various length properties) and DebugRenderMode (what is drawn, so you can select only the element types you are interested in debugging) are given. Use RapierDebugRenderPlugin::default().disabled() to add the plugin without rendering anything until it is enabled:

.add_plugins(RapierDebugRenderPlugin {
// Only draw the collider shapes and the joints.
mode: DebugRenderMode::COLLIDER_SHAPES
| DebugRenderMode::IMPULSE_JOINTS
| DebugRenderMode::MULTIBODY_JOINTS,
..default()
})

After initialization, the debug-renderer is controlled by the DebugRenderContext resource:

  • enabled switches the debug-rendering on and off.
  • mode selects what is drawn, with one boolean per flag of DebugRenderMode (so it can be edited by the tools based on Bevy's reflection, like the other fields of this resource).
  • style gives the colors and the lengths of the lines.
  • default_collider_debug selects whether the collider shapes are drawn by default (ColliderDebug::AlwaysRender) or only for the colliders asking for it (ColliderDebug::NeverRender).
  • scale_lengths_by_length_unit (enabled by default) makes the lengths of the style expressed in meters: they are multiplied by the length unit of each physics context, e.g., by the pixels-per-meter in 2D.
fn modify_debug_render(mut debug_render: ResMut<DebugRenderContext>) {
// Toggle the debug-renderer.
debug_render.enabled = !debug_render.enabled;
// Draw the contacts and the AABBs too.
debug_render.mode.contacts = true;
debug_render.mode.collider_aabbs = true;
// Expressed in meters: multiplied by the length unit of each context.
debug_render.style.rigid_body_axes_length = 1.0;
}

Finally, the rendering of individual objects can be customized by adding the following components to their entities:

  • ColliderDebugColor overrides the color of the collider (and of its AABB).
  • ColliderDebug overrides the default_collider_debug of the DebugRenderContext for this collider (its shape, its AABB, and the contact pairs it is involved in).
  • DebugRenderColor overrides the color of everything attached to the entity: its collider (unless it has a ColliderDebugColor), its rigid-body axes, its joint, and its soft-body.
  • DebugRenderVisibility::Hidden hides everything attached to the entity (except a collider with a ColliderDebug component).
// This collider is drawn in red.
commands.spawn((
Transform::from_xyz(0.0, 400.0, 0.0),
RigidBody::Dynamic,
Collider::ball(50.0),
ColliderDebugColor(Hsla::hsl(0.0, 1.0, 0.5)),
));
// Everything attached to this entity (its collider, its rigid-body, its joint, etc.) is
// drawn in blue.
commands.spawn((
Transform::from_xyz(200.0, 400.0, 0.0),
RigidBody::Dynamic,
Collider::cuboid(50.0, 50.0),
DebugRenderColor(Hsla::hsl(220.0, 1.0, 0.3)),
));
// Nothing attached to this entity is drawn.
commands.spawn((
Transform::from_xyz(-200.0, 400.0, 0.0),
RigidBody::Dynamic,
Collider::cuboid(50.0, 50.0),
DebugRenderVisibility::Hidden,
));
// The shape of this collider is never drawn, whatever the `default_collider_debug`.
commands.spawn((
Transform::from_xyz(-400.0, 400.0, 0.0),
Collider::cuboid(50.0, 50.0),
ColliderDebug::NeverRender,
));
warning

The debug-rendering is not free: it walks every collider of the scene and converts its shape into lines at each frame. Therefore it is meant to be enabled only when debugging rather than a player-facing representation of the game objects.