Crate bevy_xpbd_2d
source ·Expand description
§Bevy XPBD (deprecated in favor of Avian)
⚠️ Bevy XPBD has been deprecated in favor of its successor Avian. No further development or maintenance will be done for Bevy XPBD. See #346 for background.
Bevy XPBD is a 2D and 3D physics engine based on Extended Position Based Dynamics (XPBD) for the Bevy game engine.
Check out the GitHub repository for more information about the design, read the Getting started guide below to get up to speed, and take a look at the Table of contents for an overview of the engine’s features and their documentation.
You can also check out the FAQ, and if you encounter any further problems, consider saying hello on the Bevy Discord!
§Getting started
This short guide should help you get started with Bevy XPBD.
§Add the dependency
First, add bevy_xpbd_2d
or bevy_xpbd_3d
to the dependencies in your Cargo.toml
:
# For 2D applications:
[dependencies]
bevy_xpbd_2d = "0.5"
# For 3D applications:
[dependencies]
bevy_xpbd_3d = "0.5"
# If you want to use the most up-to-date version, you can follow the main branch:
[dependencies]
bevy_xpbd_3d = { git = "https://github.com/Jondolf/bevy_xpbd", branch = "main" }
You can specify features by disabling the default features and manually adding the feature flags you want:
[dependencies]
# Add 3D Bevy XPBD with double-precision floating point numbers.
# `parry-f64` enables collision detection using Parry.
bevy_xpbd_3d = { version = "0.5", default-features = false, features = ["3d", "f64", "parry-f64"] }
§Feature flags
Feature | Description | Default feature |
---|---|---|
2d | Enables 2D physics. Incompatible with 3d . | Yes (bevy_xpbd_2d ) |
3d | Enables 3D physics. Incompatible with 2d . | Yes (bevy_xpbd_3d ) |
f32 | Enables f32 precision for physics. Incompatible with f64 . | Yes |
f64 | Enables f64 precision for physics. Incompatible with f32 . | No |
default-collider | Enables the default Collider . Required for spatial queries. Requires either the parry-f32 or parry-f64 feature. | Yes |
parry-f32 | Enables the f32 version of the Parry collision detection library. Also enables the default-collider feature. | Yes |
parry-f64 | Enables the f64 version of the Parry collision detection library. Also enables the default-collider feature. | No |
debug-plugin | Enables physics debug rendering using the PhysicsDebugPlugin . The plugin must be added separately. | Yes |
enhanced-determinism | Enables increased determinism. | No |
parallel | Enables some extra multithreading, which improves performance for larger simulations but can add some overhead for smaller ones. | Yes |
simd | Enables SIMD optimizations. | No |
serialize | Enables support for serialization and deserialization using Serde. | No |
§Install the plugin
Bevy XPBD is designed to be very modular. It is built from several plugins that
manage different parts of the engine. These plugins can be easily initialized and configured through
the PhysicsPlugins
plugin group.
use bevy::prelude::*;
use bevy_xpbd_2d::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, PhysicsPlugins::default()))
// ...your other plugins, systems and resources
.run();
}
Now you can use all of Bevy XPBD’s components and resources to build whatever you want!
For example, adding a rigid body with a collider is as simple as spawning an entity
with the RigidBody
and Collider
components:
use bevy::prelude::*;
use bevy_xpbd_2d::prelude::*;
fn setup(mut commands: Commands) {
commands.spawn((RigidBody::Dynamic, Collider::circle(0.5)));
}
You can find lots of usage examples in the project’s repository.
§Table of contents
Below is a structured overview of the documentation for the various features of the engine.
§Rigid bodies
- Rigid body types
- Creating rigid bodies
- Movement
- Gravity and gravity scale
- Mass properties
- Linear and angular velocity damping
- Lock translational and rotational axes
- Dominance
- Automatic deactivation with sleeping
§Collision detection
- Colliders
- Creation
- Density
- Friction and restitution (bounciness)
- Collision layers
- Sensors
- Get colliding entities
- Collision events
- Accessing, filtering and modifying collisions
- Manual contact queries
§Constraints and joints
- Constraints (advanced)
- Joints
Joint motors and articulations are not supported yet, but they will be implemented in a future release.
§Spatial queries
§Configuration
- Gravity
- Physics timestep
- Physics speed
- Configure simulation fidelity with substeps
- Render physics objects for debugging
§Scheduling
- Schedules and sets
PhysicsSet
PhysicsSchedule
andPhysicsStepSet
SubstepSchedule
andSubstepSet
PostProcessCollisions
schedule- [
PrepareSet
]
- Configure the schedule used for running physics
- Pausing, resuming and stepping physics
- Usage on servers
§Architecture
- List of plugins and their responsibilities
- What is Extended Position Based Dynamics?
- Extending and modifying the engine
§Frequently asked questions
- How does Bevy XPBD compare to Rapier and bevy_rapier?
- Why is nothing happening?
- Why is everything moving so slowly?
- Why did my rigid body suddenly vanish?
- Why is performance so bad?
- Why does my camera following jitter?
- Is there a character controller?
- Why are there separate
Position
andRotation
components? - Can the engine be used on servers?
- Something else?
§How does Bevy XPBD compare to Rapier and bevy_rapier?
Rapier is the biggest and most used physics engine in the Rust ecosystem, and it is currently the most mature and feature-rich option.
bevy_rapier
is a great physics integration for Bevy, but it does have several problems:
- It has to maintain a separate physics world and synchronize a ton of data with Bevy each frame
- The source code is difficult to inspect, as the vast majority of it is glue code and wrappers for Bevy
- It has poor docs.rs documentation, and the documentation on rapier.rs is often outdated and missing features
- It is hard to extend as it’s not very modular or composable in design
- Overall, it doesn’t have a native ECS-like feel outside of its public API
Bevy XPBD on the other hand is built for Bevy with Bevy, and it uses the ECS for both the internals and the public API. This removes the need for a separate physics world, reduces overhead, and makes the source code much more approachable and easy to inspect for Bevy users.
In part thanks to Bevy’s modular architecture and the ECS, Bevy XPBD is also highly composable, as it consists of several independent plugins and provides lots of options for configuration and extensions, from custom schedules and plugins to custom joints and constraints.
In terms of the physics implementation, Rapier uses an impulse/velocity based solver, while Bevy XPBD uses Extended Position Based Dynamics. On paper, XPBD should be more stable and robust, but it hasn’t been widely adopted in mainstream usage yet.
One of the biggest disadvantages of Bevy XPBD is that it is still very young, so it can have lots of bugs, some missing features, and fewer community resources and third party crates. However, it is growing quite rapidly, and it is already pretty close to feature-parity with Rapier.
At the end of the day, both engines are very solid options. If you are looking for a more mature and tested
physics integration, bevy_rapier
is the better choice, but if you prefer an engine with less overhead
and a more native Bevy integration, consider using Bevy XPBD. Their core APIs are also quite similar,
so switching between them should be straightforward.
§Why is nothing happening?
Make sure you have added the PhysicsPlugins
plugin group and you have given your rigid bodies
a RigidBody
component. See the getting started section.
§Why is everything moving so slowly?
If your application is in 2D, you might be using pixels as length units. This will require you to use
larger velocities and forces than you would in 3D. Make sure you set Gravity
to some larger value
as well, because its magnitude is 9.81 by default, which is tiny in pixels.
Bevy XPBD doesn’t have a “physics scale” yet, but it will most likely be added in the future so that it’s possible to define some kind of pixels per meter configuration.
§Why did my rigid body suddenly vanish?
Make sure to give your rigid bodies some mass, either by adding a Collider
or a MassPropertiesBundle
. If your bodies don’t have any mass, any physical interaction is likely to
instantly give them infinite velocity.
Bevy XPBD should automatically print warnings when it detects bodies with an invalid mass or inertia.
§Why is performance so bad?
Make sure you are building your project in release mode using cargo build --release
.
You can further optimize builds by setting the number of codegen units in your Cargo.toml
to 1,
although this will also increase build times.
[profile.release]
codegen-units = 1
Note that Bevy XPBD simply isn’t very optimized yet, and it mostly runs on a single thread for now. This will be addressed in future releases.
§Why does my camera following jitter?
When you write a system that makes the camera follow a physics entity, you might notice some jitter.
To fix this, the system needs to:
- Run after physics so that it has the up-to-date position of the player.
- Run before transform propagation so that your changes to the camera’s
Transform
are written to the camera’sGlobalTransform
before the end of the frame.
The following ordering constraints should resolve the issue.
app.add_systems(
PostUpdate,
camera_follow_player
.after(PhysicsSet::Sync)
.before(TransformSystem::TransformPropagate),
);
§Is there a character controller?
Bevy XPBD does not have a built-in character controller, so if you need one,
you will need to implement it yourself. However, third party character controllers
like bevy_tnua
support Bevy XPBD, and bevy_mod_wanderlust
and others are also likely to get Bevy XPBD support soon.
For custom character controllers, you can take a look at the
dynamic_character_2d
and kinematic_character_2d
examples to get started.
§Why are there separate Position
and Rotation
components?
While Transform
can be used for the vast majority of things, Bevy XPBD internally
uses separate Position
and Rotation
components. These are automatically
kept in sync by the SyncPlugin
.
There are several reasons why the separate components are currently used.
- Position and rotation should be global from the physics engine’s point of view.
- Transform scale and shearing can cause issues and rounding errors in physics.
- Transform hierarchies can be problematic.
- There is no
f64
version ofTransform
. - There is no 2D version of
Transform
(yet), and having a 2D version can optimize several computations. - When position and rotation are separate, we can technically have more systems running in parallel.
- Only rigid bodies have rotation, particles typically don’t (although we don’t make a distinction yet).
In external projects however, using Position
and Rotation
is only necessary when you
need to manage positions in the SubstepSchedule
. Elsewhere, you should be able to use Transform
.
There is also a possibility that we will revisit this if/when Bevy has a Transform2d
component.
Using Transform
feels more idiomatic and simple, so it would be nice if it could be used directly
as long as we can get around the drawbacks.
§Can the engine be used on servers?
Yes! Networking often requires running the simulation in a specific schedule, and in Bevy XPBD you can set the schedule that runs physics and configure the timestep to whatever you want.
One configuration is to run the client in FixedUpdate
, and to use a fixed timestep for Time<Physics>
on both the server and the client to make sure the physics simulation is only advanced by one step
each time the schedule runs.
Note that while Bevy XPBD should be locally deterministic, it can produce slightly different results on different machines.
§Something else?
Physics engines are very large and Bevy XPBD is young, so stability issues and bugs are to be expected.
If you encounter issues, please consider first taking a look at the issues on GitHub and open a new issue if there already isn’t one regarding your problem.
You can also come and say hello on the Bevy Discord server. There you can find a bevy_xpbd thread on the crate-help channel where you can ask questions.
§What is XPBD?
XPBD or Extended Position Based Dynamics is a physics simulation method that extends the traditional PBD to be more physically accurate and less dependent on time step size and iteration count.
Unlike force or impulse based physics simulation methods, XPBD mostly operates at the position-level, which can produce more stable and reliable results, while allowing straightforward coupling of rigid bodies, soft bodies and fluids.
§Simulation loop
At a high level, XPBD consists of a broad phase followed by a substepping loop that handles position integration, constraint solving, velocity updates, and a velocity solver that handles dynamic friction and restitution.
It looks roughly like this:
while simulating:
// Substep size
h = ∆t / substep_count
// Broad phase
broad_collision_pairs = collect_collision_pairs()
for substep_count:
// Integrate
for n particles and bodies:
// Integrate position
x_prev = x
v = v + h * f_ext / m
x = x + h * v
// Integrate rotation
q_prev = q
ω = ω + h * I^-1 * (τ_ext - (ω x (I * ω)))
q = q + h * 0.5 * [ω_x, ω_y, ω_z, 0] * q
q = q / |q|
// Narrow phase
for pair in broad_collision_pairs:
compute_contacts(pair)
// Solve constraints (contacts, joints etc.)
solve_constraints(particles and bodies)
// Update velocities
for n particles and bodies:
v = (x - x_prev) / h
∆q = q * q_prev^-1
ω = 2 * [∆q_x, ∆q_y, ∆q_z] / h
ω = ∆q_w >= 0 ? ω : -ω
// Solve velocity constraints (dynamic friction and restitution)
solve_velocities(particles and bodies)
where h
is the substep size, q
is the rotation as a quaternion,
ω
is the angular velocity, I
is the angular inertia tensor and τ
is the
external torque.
In Bevy XPBD, the simulation loop is handled by various plugins. The PhysicsSetupPlugin
sets up
the Bevy schedules12 and sets345, the BroadPhasePlugin
manages the broad phase, the IntegratorPlugin
handles XPBD integration, and so on. You can find all of the plugins and their responsibilities here.
§See also
- XPBD integration step
- Constraints and how to create them
- Schedules and sets used for the simulation loop
§Learning resources
If you want to learn more about XPBD, I recommend taking a look at some of the papers. Especially the first one from 2020 was used heavily for the simulation loop and constraints in Bevy XPBD.
- XPBD: Müller M, Macklin M, Chentanez N, Jeschke S, Kim T. 2020. Detailed Rigid Body Simulation with Extended Position Based Dynamics.
- XPBD: Macklin M, Müller M, Chentanez N. 2016. XPBD: Position-Based Simulation of Compliant Constrained Dynamics.
The papers are quite academic, so you might instead prefer some videos and articles. The first one by Ten Minute Physics (Matthias Müller, one of the XPBD researchers) is great for understanding how XPBD differs from other simulation methods and how the constraints work.
- Video: Ten Minute Physics. 2022. Getting ready to simulate the world with XPBD.
- Notes: Nolan Tait. Bevy Physics: XPBD.
- Tutorial series: Johan Helsing. Tutorial: Making a physics engine with Bevy. (inspired this project)
§License
Bevy XPBD is free and open source. All code in the Bevy XPBD repository is dual-licensed under either:
- MIT License (LICENSE-MIT or http://opensource.org/licenses/MIT)
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
at your option.
Re-exports§
pub extern crate parry2d as parry;
Modules§
- Commonly used components.
- Contains constraints used by the solver.
- Math types and traits used in the crate. Most of the math types are feature-dependent, so they will be different for
2d
/3d
andf32
/f64
. - The building blocks of Bevy XPBD.
- Re-exports common components, bundles, resources, plugins and types.
- Resources used in the simulation.
Structs§
- Responsible for advancing the physics simulation. This is run in
PhysicsSet::StepSimulation
. - A schedule where you can add systems to filter or modify collisions using the
Collisions
resource. - The substepping schedule that runs in
PhysicsStepSet::Substeps
. The number of substeps per physics step is configured through theSubstepCount
resource.
Enums§
- High-level system sets for the main phases of the physics engine. You can use these to schedule your own systems before or after physics is run without having to worry about implementation details.
- System sets for the main steps in the physics simulation loop. These are typically run in the
PhysicsSchedule
. - System sets for the the steps in the inner substepping loop. These are typically run in the
SubstepSchedule
.