bevy_boxddd 0.1.0

Bevy integration for the boxddd Rust bindings to Box3D
Documentation

bevy_boxddd

bevy_boxddd integrates boxddd with Bevy 0.19. It keeps the core boxddd crate engine-agnostic while providing ECS authoring, fixed-step systems, messages, queries, debug drawing, and teaching examples for Bevy users.

Quick Facts

Item Value
Bevy version 0.19.0
Rust version 1.95.0 or newer
Physics owner NonSend<BoxdddPhysicsContext>
Schedule FixedUpdate
Default rendering deps None
Debug rendering Optional debug-gizmos feature
Picking example Optional physics-picking feature
Threading Keep boxddd::World on the Bevy main thread; move snapshots across threads

Quickstart

use bevy::prelude::*;
use bevy_boxddd::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(BoxdddPhysicsPlugin::default())
        .add_systems(Startup, setup)
        .run();
}

fn setup(mut commands: Commands) {
    let body = commands
        .spawn((
            RigidBody::Dynamic,
            Transform::from_xyz(0.0, 4.0, 0.0),
        ))
        .id();

    commands.spawn((Collider::sphere(0.35), ChildOf(body)));
    commands.spawn((Collider::cube(0.4), ChildOf(body)));
}

Child collider entities are plugin-owned shapes attached to the nearest parent entity with BoxdddBody. A body entity can also carry its own Collider.

Components

  • RigidBody: Static, Kinematic, or Dynamic.
  • BodySettings: gravity scale, damping, sleeping, bullet CCD, and motion locks applied to the native body.
  • Collider: basic cuboid, cube, sphere, and capsule_y descriptors plus advanced mesh, height-field, compound, created-hull, and transformed-hull descriptors.
  • PhysicsMaterial: density, friction, restitution, sensor/contact flags, and Box3D filter data.
  • JointTarget + Joint: declarative joint authoring between two Bevy body entities.
  • TransformSyncMode: dynamic bodies default to physics-authored transforms; static and kinematic bodies default to Bevy-authored transforms.
  • LinearVelocity, AngularVelocity, ExternalForce, ExternalImpulse: control inputs applied before stepping.
  • BoxdddBody, BoxdddShape, BoxdddJoint: native id components inserted by the plugin after successful creation.

Advanced collider descriptors that create Box3D native resource shapes are static-body only. Attaching them to dynamic bodies emits BoxdddErrorMessage { operation: CreateShape, error: InvalidArgument, .. }.

Queries And Picking

Default library helpers are renderer-free:

let context = world.get_non_send::<BoxdddPhysicsContext>().unwrap();
let hit = cast_ray_closest(
    context,
    Vec3::new(-2.0, 0.0, 0.0),
    Vec3::new(5.0, 0.0, 0.0),
    boxddd::QueryFilter::default(),
)?;

Hits include both the Box3D ShapeId and the mapped Bevy entity when the shape is plugin-owned.

Debug Draw

The plugin always exposes BoxdddDebugDrawSettings and BoxdddDebugDrawCommands. By default collection is disabled. Enable collection without rendering dependencies:

commands.insert_resource(BoxdddDebugDrawSettings {
    enabled: true,
    options: boxddd::DebugDrawOptions::default(),
});

Enable debug-gizmos to render collected commands through Bevy Gizmos:

cargo run -p bevy_boxddd --features debug-gizmos --example debug_draw_overlay_3d

Messages And Errors

The plugin registers Bevy messages for errors, body moves, contact begin/end/hit, and sensor begin/end. Recoverable errors follow BoxdddPhysicsSettings.error_policy: message only, message plus log, or panic.

Examples

The visible examples complement the core headless examples and follow the official Box3D sample parity map in docs/upstream-parity/box3d-sample-matrix.md.

Example Run command Purpose
falling_stack_3d cargo run -p bevy_boxddd --example falling_stack_3d Basic windowed stack with plugin-driven transforms.
contact_messages_3d cargo run -p bevy_boxddd --example contact_messages_3d Reads contact messages and updates Bevy materials.
debug_gizmos_3d cargo run -p bevy_boxddd --example debug_gizmos_3d App-authored collider gizmos without Box3D debug draw collection.
advanced_colliders_3d cargo run -p bevy_boxddd --example advanced_colliders_3d Static mesh, height-field, compound, hull-backed colliders, and dynamic bodies falling onto them.
joint_gallery_3d cargo run -p bevy_boxddd --example joint_gallery_3d Visible connected bodies using every public declarative joint variant.
debug_draw_overlay_3d cargo run -p bevy_boxddd --features debug-gizmos --example debug_draw_overlay_3d Box3D debug draw commands rendered through Bevy Gizmos.
physics_picking_3d cargo run -p bevy_boxddd --features physics-picking --example physics_picking_3d Camera/cursor ray mapped through Box3D queries, not mesh picking.
testbed_3d cargo run -p bevy_boxddd --features "debug-gizmos physics-picking" --example testbed_3d Switchable teaching scenes for stacks, advanced colliders, body controls, continuous collision, character mover probes, materials, joints, contacts, picking, and debug draw.

The testbed scene keys are 1 falling stack, 2 advanced colliders, 3 body controls, 4 continuous collision, 5 character mover, 6 materials, 7 joints, 8 contacts, 9 ray picking, and 0 debug draw.

Platform And Concurrency Boundaries

Native desktop targets are the supported runtime target for the Bevy plugin. CI checks Windows, Linux, and macOS native builds through the workspace test suite, and checks the Bevy examples on Linux with the required windowing/audio packages installed.

wasm32-unknown-unknown is compile-only for the minimal library surface; windowed examples are native-only in this release. Mobile targets are also compile-only at the core boxddd layer and are not yet runtime targets for bevy_boxddd.

boxddd::World is intentionally non-send and lives in BoxdddPhysicsContext. Do not move it into Bevy worker systems. The core crate has TaskSystem::blocking_threads() for Box3D's native task callbacks, but Bevy task-pool integration is deferred until that contract has more usage.

Development Checks

cargo fmt --all --check
cargo check -p bevy_boxddd --no-default-features
cargo nextest run -p bevy_boxddd
cargo check -p bevy_boxddd --examples
cargo check -p bevy_boxddd --features debug-gizmos --example debug_draw_overlay_3d
cargo check -p bevy_boxddd --features physics-picking --example physics_picking_3d
cargo check -p bevy_boxddd --features "debug-gizmos physics-picking" --example testbed_3d
cargo check -p bevy_boxddd --target wasm32-unknown-unknown --no-default-features

Windowed teaching examples:

cargo run -p bevy_boxddd --example falling_stack_3d
cargo run -p bevy_boxddd --example advanced_colliders_3d
cargo run -p bevy_boxddd --example joint_gallery_3d
cargo run -p bevy_boxddd --features debug-gizmos --example debug_draw_overlay_3d
cargo run -p bevy_boxddd --features physics-picking --example physics_picking_3d
cargo run -p bevy_boxddd --features "debug-gizmos physics-picking" --example testbed_3d

On Windows, the teaching examples default to the DX12 backend because some NVIDIA/Vulkan driver and validation-layer combinations emit noisy swapchain validation errors even when the app continues to run. Set WGPU_BACKEND=vulkan before running an example if you want to test Vulkan explicitly.