Avian is an ECS-driven 2D and 3D physics engine 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!
This short guide should help you get started with Avian.
First, add avian2d
or avian3d
to the dependencies in your Cargo.toml
:
# For 2D applications:
[dependencies]
avian2d = "0.2"
# For 3D applications:
[dependencies]
avian3d = "0.2"
# If you want to use the most up-to-date version, you can follow the main branch:
[dependencies]
avian3d = { git = "https://github.com/Jondolf/avian", branch = "main" }
You can specify features by disabling the default features and manually adding the feature flags you want:
[dependencies]
# Add 3D Avian with double-precision floating point numbers.
# `parry-f64` enables collision detection using Parry.
avian3d = { version = "0.2", default-features = false, features = ["3d", "f64", "parry-f64"] }
Feature | Description | Default feature |
---|---|---|
2d | Enables 2D physics. Incompatible with 3d . | Yes (avian2d ) |
3d | Enables 3D physics. Incompatible with 2d . | Yes (avian3d ) |
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 |
collider-from-mesh | Allows you to create Collider s from Mesh es. | Yes |
bevy_scene | Enables ColliderConstructorHierarchy to wait until a [Scene ] has loaded before processing it. | Yes |
bevy_picking | Enables physics picking support for bevy_picking using the [PhysicsPickingPlugin ]. The plugin must be added separately. | Yes |
debug-plugin | Enables physics debug rendering using the PhysicsDebugPlugin . The plugin must be added separately. | Yes |
enhanced-determinism | Enables cross-platform deterministic math, improving determinism across architectures at a small performance cost. | 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 |
Avian 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 avian3d::prelude::*;
use bevy::prelude::*;
fn main() {
App::new()
.add_plugins((DefaultPlugins, PhysicsPlugins::default()))
// ...your other plugins, systems and resources
.run();
}
Now you can use all of Avian’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 avian3d::prelude::*;
use bevy::prelude::*;
fn setup(mut commands: Commands) {
commands.spawn((RigidBody::Dynamic, Collider::sphere(0.5)));
}
You can find lots of usage examples in the project’s repository.
Below is a structured overview of the documentation for the various features of the engine.
Transform
interpolation and extrapolationSee the dynamics
module for more details about rigid body dynamics in Avian.
ColliderConstructor
and ColliderConstructorHierarchy
See the collision
module for more details about collision detection and colliders in Avian.
Joint motors and articulations are not supported yet, but they will be implemented in a future release.
Transform
interpolation and extrapolationPhysicsSet
PhysicsSchedule
and PhysicsStepSet
SubstepSchedule
SolverSet
and SubstepSolverSet
PostProcessCollisions
schedulePrepareSet
Position
and Rotation
components?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:
Avian 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, Avian 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.
One disadvantage of Avian is that it is still relatively young, so it can have more 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 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 Avian. Their core APIs are also quite similar,
so switching between them shouldn’t be too difficult.
Make sure you have added the PhysicsPlugins
plugin group and you have given your rigid bodies
a RigidBody
component. See the getting started section.
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.
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
To produce consistent, frame rate independent behavior, physics by default runs
in the FixedPostUpdate
schedule with a fixed timestep, meaning that the time between
physics ticks remains constant. On some frames, physics can either not run at all or run
more than once to catch up to real time. This can lead to visible stutter for movement.
This stutter can be resolved by interpolating or extrapolating the positions of physics objects
in between physics ticks. Avian has built-in support for this through the PhysicsInterpolationPlugin
,
which is included in the PhysicsPlugins
by default.
Interpolation can be enabled for an individual entity by adding the TransformInterpolation
component:
fn setup(mut commands: Commands) {
// Enable interpolation for this rigid body.
commands.spawn((
RigidBody::Dynamic,
Transform::default(),
TransformInterpolation,
));
}
To make all rigid bodies interpolated by default, use PhysicsInterpolationPlugin::interpolate_all()
:
fn main() {
App::new()
.add_plugins(PhysicsPlugins::default().set(PhysicsInterpolationPlugin::interpolate_all()))
// ...
.run();
}
See the PhysicsInterpolationPlugin
for more information.
If this does not fix the choppiness, the problem could also be related to system ordering.
If you have a system for camera following, make sure it runs after physics,
but before Bevy’s transform propagation in PostUpdate
.
app.add_systems(
PostUpdate,
camera_follow_player.before(TransformSystem::TransformPropagate),
);
Avian 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 Avian, and bevy_mod_wanderlust
and others are also likely to get Avian support soon.
For custom character controllers, you can take a look at the
dynamic_character_3d
and kinematic_character_3d
examples to get started.
Position
and Rotation
components?While Transform
can be used for the vast majority of things, Avian 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.
f64
version of Transform
.Transform
(yet), and having a 2D version can optimize several computations.In external projects however, using Position
and Rotation
is only necessary when you
need to manage positions within PhysicsSet::StepSimulation
. 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.
Yes! Networking often requires running the simulation in a specific schedule, and in Avian it is straightforward
to set the schedule that runs physics and configure the timestep if needed.
By default, physics runs at a fixed timestep in FixedPostUpdate
.
Physics engines are very large and Avian 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 an Avian Physics topic on the #ecosystem-crates
channel where you can ask questions.
Avian is free and open source. All code in the Avian repository is dual-licensed under either:
at your option.
pub extern crate parry3d as parry;
Collider
s.TypeRegistry
resource in bevy_reflect
.