Avian v0.1.0
Avian Physics 0.1 has been released! 🪶
Avian is an ECS-driven physics engine for the Bevy game engine. It is the next evolution of Bevy XPBD, with a completely rewritten contact solver, improved performance, a reworked structure, and numerous other improvements and additions over its predecessor.
See #346 for background on the rebrand.
Highlights
Avian 0.1 has a ton of improvements, additions, and fixes over Bevy XPBD 0.4. Some highlights:
- A solver rewrite: Avian uses an impulse-based TGS Soft solver instead of XPBD for contacts.
- A reworked narrow phase: Collision detection is much more performant and reliable.
- Continuous Collision Detection (CCD): Speculative collision and sweep-based CCD are implemented to prevent tunneling.
- Optional collision margins: Extra thickness can be added for thin colliders such as trimeshes to improve stability and performance.
- Improved performance: Overhead for large scenes is significantly smaller, and collision-heavy scenes can have over a 4-6x performance improvement in comparison to Bevy XPBD.
- Improved runtime collider constructors: It is easier to define colliders and collider hierarchies statically to enable more powerful scene workflows.
- Structural improvements and polish: The module structure has been heavily reworked, and tons of inconsistencies and bugs have been resolved.
- Bevy 0.14 support: Avian supports the latest version of Bevy, and internally, it already takes advantage of new features such as observers and component lifecycle hooks.
Check out the announcement blog post for a more in-depth overview of what has changed and why. A more complete changelog can also be found after the migration guide below.
Migration Guide
Note: This guide is for migration from Bevy XPBD 0.4 to Avian 0.1. The entries for migration to Bevy XPBD 0.5 (an easier migration path) still apply and are also listed here.
New Contact Solver #385
The contact solver has been rewritten. In practice, this has the following effects:
- Collisions should be much more stable.
- Resolving overlap is no longer nearly as explosive.
- Less substeps are generally needed for stability.
- Tunneling is much more rare.
- Performance is better.
However:
- Contacts may even be too soft by default for some applications. This can be tuned with the
SolverConfig
resource. - Static friction is currently not considered separately from dynamic friction. This may be fixed in the future.
- Restitution might not be quite as perfect in some instances (this is a tradeoff for speculative collision to avoid tunneling).
- 2D applications may need to configure the
PhysicsLengthUnit
to get the best stability and behavior.
The PhysicsLengthUnit
can be thought of a pixels-per-meter scaling factor for the engine's internal length-based tolerances and thresholds, such as the maximum speed at which overlap is resolved, or the speed threshold for allowing bodies to sleep. It does not scale common user-facing inputs or outputs like colliders or velocities.
To configure the PhysicsLengthUnit
, you can insert it as a resource, or simply set it while adding PhysicsPlugins
:
fn main() {
App::new()
.add_plugins((
DefaultPlugins,
// A 2D game with 20 pixels per meter
PhysicsPlugins::default().with_length_unit(20.0),
))
.run();
}
Collider
Constructor Argument Order #394
To match Bevy's Cylinder
, Capsule
, and Cone
, the order of arguments has changed for some Collider
constructors.
- Use
Collider::cylinder(radius, height)
instead ofCollider::cylinder(height, radius)
. - Use
Collider::capsule(radius, height)
instead ofCollider::capsule(height, radius)
. - Use
Collider::capsule_endpoints(radius, a, b)
instead ofCollider::capsule_endpoints(a, b, radius)
. - Use
Collider::cone(radius, height)
instead ofCollider::cone(height, radius)
.
This is a very heavily breaking change, but I believe it is important that we align ourselves with Bevy here, and it's better to do it sooner rather than later.
AsyncCollider
and AsyncSceneCollider
#378
AsyncCollider
, AsyncSceneCollider
, and ComputedCollider
have been replaced by more powerful ColliderConstructor
and ColliderConstructorHierarchy
types. They work similarly, but also support primitive shapes and arbitrary hierarchies, not just colliders computed for meshes and scenes.
Additionally, some naming changes have been made to improve consistency, such as renaming TriMesh
to Trimesh
to be consistent with Collider::trimesh
.
- Remove feature
async-collider
. If you need to use computed shapes, use the featurecollider-from-mesh
. If you depend onColliderConstructorHierarchy
waiting for a scene to load, use the featurebevy_scene
- Remove
AsyncCollider
and useColliderConstructor
directly - Rename
AsyncSceneCollider
toColliderConstructorHierarchy
- Rename
AsyncSceneCollider::default_shape
toColliderConstructorHierarchy::default_constructor
- Rename
AsyncSceneCollider::meshes_by_name
toColliderConstructorHierarchy::config
- Rename
AsyncSceneCollider::with_shape_for_name
toColliderConstructorHierarchy::with_constructor_for_name
- Rename
AsyncSceneCollider::without_shape_for_name
toColliderConstructorHierarchy::without_constructor_for_name
- Rename
- Rename
AsyncSceneColliderData
toColliderConstructorHierarchyConfig
- Rename
AsyncSceneColliderData::shape
toColliderConstructorHierarchyConfig::constructor
- Rename
- Rename
ComputedCollider
toColliderConstructor
.- Rename
ComputedCollider::TriMesh
toColliderConstructor::TrimeshFromMesh
- Rename
ComputedCollider::TriMeshWithFlags
toColliderConstructor::TrimeshFromMeshWithConfig
- Rename
ComputedCollider::ConvexHull
toColliderConstructor::ConvexHullFromMesh
- Rename
ComputedCollider::ConvexDecomposition
toColliderConstructor::ConvexDecompositionFromMeshWithConfig
- Rename
- Rename
VHACDParameters
toVhacdParameters
- Rename
Collider::halfspace
toCollider::half_space
Reworked Module Structure #370
- The internal module structure has changed significantly, and types have moved around. Most imports from the
prelude
should work like before, but explicit import paths may be broken. - The
PhysicsSetupPlugin
has been split intoPhysicsSchedulePlugin
andPhysicsTypeRegistrationPlugin
.
Sensor Mass Properties #381
Colliders with the Sensor
component no longer contribute to the mass properties of rigid bodies. You can add mass for them by adding another collider that is not a sensor, or by manually adding mass properties with the MassPropertiesBundle
or its components.
Additionally, the mass properties of Sensor
colliders are no longer updated automatically, unless the Sensor
component is removed.
Joints and Custom Constraints #390 and #385
SphericalJoint
no longer exists in 2D. UseRevoluteJoint
instead.AngleLimit
propertiesalpha
andbeta
are now namedmin
andmax
.apply_positional_correction
has been renamed toapply_positional_lagrange_update
. There is also anapply_positional_impulse
method.apply_angular_correction
has been renamed toapply_angular_lagrange_update
. There is also anapply_angular_impulse
method.compute_lagrange_update
no longer takes a slice over gradients. For that, usecompute_lagrange_update_with_gradients
.Joint::align_orientation
has been moved toAngularConstraint
.- XPBD traits and systems are now located in the
dynamics::solver::xpbd
module. - User constraints should run
solve_constraints
inSubstepSolverSet::SolveUserConstraints
instead ofSubstepSet::SolveUserConstraints
.
Scheduling Changes #385 and #380
Several scheduling internals have been changed. For example:
- The narrow phase and
PostProcessCollisions
schedule are now run inPhysicsStepSet::NarrowPhase
instead ofSubstepSet::NarrowPhase
. - Integration is now run in
IntegrationSet::Velocity
andIntegrationSet::Position
instead ofSubstepSet::Integrate
. SubstepSet
has been removed.- The solver runs in
PhysicsStepSet::Solver
. - The solver's system sets are in
SolverSet
. - Substepping is performed in
SolverSet::Substep
. - The substepping loop's system sets are in
SubstepSolverSet
.
- The solver runs in
Systems running in PostProcessCollisions
may need to be modified to account for it being moved outside of the substepping loop.
Some PrepareSet
system sets have also changed order.
Before:
PreInit
PropagateTransforms
InitRigidBodies
InitMassProperties
InitColliders
InitTransforms
Finalize
After:
PreInit
InitRigidBodies
InitColliders
PropagateTransforms
InitMassProperties
InitTransforms
Finalize
ColliderHierarchyPlugin
#377
Hierarchy and transform logic for colliders has been extracted from the ColliderBackendPlugin
into a new ColliderHierarchyPlugin
, which by default is included in the PhysicsPlugins
plugin group.
If you are adding plugins manually, make sure you have both if you want that functionality.
Rotation
Component #370
The Rotation
component has been updated to match the API of Bevy's new Rot2
type more closely.
The primary breaking changes are that rotate
and mul
have been deprecated in favor of Mul
implementations, and the 2D from_radians
and from_degrees
have been renamed to just radians
and degrees
.
// Before
let rotation = Rotation::from_degrees(45.0);
assert_eq!(rotation.mul(rotation).rotate(Vec2::X), Vec2::Y);
// After
let rotation = Rotation::degrees(45.0);
assert_eq!(rotation * rotation * Vec2::X, Vec2::Y);
Add
and Sub
implementations have also been removed, as adding or subtracting quaternions in 3D is not quite equivalent to performing rotations, which can be a footgun, and having the 2D version function differently would also be inconsistent.
What's Changed
Note: These are changes made between Bevy XPBD 0.4 and Avian 0.1.
- Fix time of impact description in
ShapeHits
by @Jondolf in #340 - Fix 2D heightfield scale and docs by @Jondolf in #343
- Fix 3D ShapeCaster global_rotation by @ramon-oliveira in #344
- Normalize rotations after solving constraints in solver by @Jondolf in #345
- Add feature to examples_common to enable PhysicsDebugPlugin by @jpedrick in #339
- Use
compile_error!
macro instead of panicking inPhysicsLayer
derive macro by @doonv in #347 - Fix some doc tests by @yrns in #354
- various fixes in the
prepare/init_transforms
system by @exoexo-dev in #360 - Implement
RegularPolygon
colliders with a custom shape by @Jondolf in #367 - Rework module structure, and improve documentation and
Rotation
by @Jondolf in #370 - Improve trimesh docs by @janhohenheim in #373
- Apply collider scale before physics instead of afterwards by @Jondolf in #374
- Fix collider scale for child rigid bodies by @Jondolf in #375
- Update bevy-0.14 branch to crates.io release of nalgebra by @gmorenz in #372
- Speed up
ColliderTransform
propagation and extract collider hierarchy logic intoColliderHierarchyPlugin
by @Jondolf in #377 - Refactor and speed up transform propagation and hierarchies further by @Jondolf in #380
- Make sensors not contribute to mass properties by @Jondolf in #381
- Rework deferred collider initialization by @janhohenheim in #378
- Fix angular corrections for some 3D joints by @Jondolf in #388
- Rework contact solver and collision detection, implement speculative collision by @Jondolf in #385
- Clean up and refactor joint logic by @Jondolf in #390
- Implement sweep-based CCD by @Jondolf in #391
- Fix inconsistency between collider constructors and Bevy's primitives by @Jondolf in #394
- Implement collision margin by @Jondolf in #393
- Add
#[reflect(Serialize, Deserialize)]
and register more types by @Jondolf in #395
New Contributors
- @ramon-oliveira made their first contribution in #344
- @jpedrick made their first contribution in #339
- @doonv made their first contribution in #347
- @yrns made their first contribution in #354
- @exoexo-dev made their first contribution in #360
- @janhohenheim made their first contribution in #373
- @gmorenz made their first contribution in #372
Full Changelog: xpbd-v0.4.0...v0.1.0