Skip to content

Releases: avianphysics/avian

Avian v0.7.0

Choose a tag to compare

@Jondolf Jondolf released this 20 Jun 21:00
965e85b

Avian Physics 0.7 has been released! 🪶

Avian 0.7 cover image

Avian 0.7 is primarily just an update to Bevy 0.19.

See the Avian 0.7 announcement post and migration guide for more details.

What's Changed

New Contributors

Full Changelog: v0.6.1...v0.7.0

v0.6.1

Choose a tag to compare

@Jondolf Jondolf released this 23 Mar 01:54

What's Changed

New Contributors

Full Changelog: v0.6.0...v0.6.1

Avian v0.6.0

Choose a tag to compare

@Jondolf Jondolf released this 16 Mar 21:32
3421b21

Avian Physics 0.6 has been released! 🪶

Avian 0.6 cover image

Highlights

Avian 0.6 brings several major optimizations and features:

  • Move-and-slide: Avian now supports move-and-slide, the fundamental movement and collision algorithm used by Kinematic Character Controllers (KCC).
  • Joint motors: Revolute joints and prismatic joints now support motors with both velocity and position control.
  • BVH broad phase: Broad phase collision detection now uses OBVHS, massively improving performance for large scenes and static geometry.
  • Spatial query optimizations: Spatial queries now reuse the BVH used by the broad phase, significantly reducing overhead.

Check out the announcement blog post for a more in-depth overview of what has changed and why. A migration guide can be found here.

What's Changed

New Contributors

Full Changelog: v0.4.1...v0.6.0

v0.6.0-rc.1

v0.6.0-rc.1 Pre-release
Pre-release

Choose a tag to compare

@Jondolf Jondolf released this 07 Feb 17:21

A full diff of what's in the release candidate can be seen here: v0.5.0...v0.6.0-rc.1

Avian v0.5.0

Choose a tag to compare

@Jondolf Jondolf released this 17 Jan 01:08

Avian Physics 0.5 has been released! 🪶

Avian 0.5 cover image

Avian 0.5 is just an update to Bevy 0.18, with no other breaking changes. See Bevy's own release notes for more details.

This was the first release under our new release process, where we publish Bevy version updates separately from feature releases, to unblock users and third party crates that want to migrate to the latest Bevy release early. A separate Avian 0.6 feature release with new functionality and improvements will be published when it is ready.

See the Avian 0.5 announcement post for more details.

v0.4.1

Choose a tag to compare

@Jondolf Jondolf released this 01 Nov 14:21

What's Changed

  • Implement trimesh builder by @janhohenheim in #866
  • Store migration guides in the repository by @Jondolf in #867
  • Rename C-Breaking-Change to M-Migration-Guide by @Jondolf in #870
  • Fix issue with RayCaster when max_hits is set to 1 by @LlamaLamp in #869
  • Fix init_physics_transform running twice and breaking scene hierarchies by @Jondolf in #873
  • Prune manifolds without points by @kristoff3r in #879
  • Fix locked axes for angular impulses by @Jondolf in #881
  • Update 3D character examples link by @ostin-r in #878
  • Fix panic when despawning joints after despawning their bodies by @Jondolf in #882

New Contributors

Full Changelog: v0.4.0...v0.4.1

Avian v0.4.0

Choose a tag to compare

@Jondolf Jondolf released this 13 Oct 12:00
8add248

Avian Physics 0.4 has been released! 🪶

Avian 0.4 cover image

Highlights

Avian 0.4 is the biggest release yet, with several new features, quality-of-life improvements, and important bug fixes. Highlights include:

  • Massive performance improvements: Avian is 3x as fast as before, with much better scaling for multi-core hardware.
    • Solver bodies: The solver stores bodies in a much more efficient format optimized for cache locality and future wide SIMD support.
    • Graph coloring: The constraint solver is now multi-threaded with graph coloring.
    • Simulation islands: Islands are used for a much improved sleeping and waking system, reducing overhead for large game worlds with many resting bodies.
  • Force overhaul: The force and impulse APIs have been redesigned from the ground up, providing a much more capable and intuitive interface.
  • Joint Improvements: Joints now support full reference frames (anchor + basis), and have new JointDamping and JointForces components.
  • Voxel colliders: Avian now supports voxel colliders for efficient representation of Minecraft-like worlds and other volumetric data.
  • Bevy 0.17 support: Avian has been updated to the latest version of Bevy, and has changed its collision event types and system set naming to match.
  • Contact API improvements: Contact data now provides access to world-space points, normal speeds, and more accurate contact impulses.
  • Benchmarking CLI: Avian has a new CLI tool for benchmarking various scenes and profiling multi-threaded scaling.

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

Bevy 0.17 #815

Avian 0.4 migrates Avian to Bevy 0.17. This involves some breaking changes.

Collision Events

The CollisionStarted, CollisionEnded, OnCollisionStart, and OnCollisionEnd events have been replaced by the CollisionStart and CollisionEnd events. They are both written as a Message and triggered as an Event, and store the collider and body entity of both colliders involved in the event.

A collision event observer before:

fn on_player_stepped_on_plate(event: Trigger<OnCollisionStart>, player_query: Query<&Player>) {
    let pressure_plate = event.target();
    let other_entity = event.collider;

    if player_query.contains(other_entity) {
        println!("Player {other_entity} stepped on pressure plate {pressure_plate}");
    }
}

and after:

fn on_player_stepped_on_plate(event: On<CollisionStart>, player_query: Query<&Player>) {
    let pressure_plate = event.collider1;
    let other_entity = event.collider2;

    if player_query.contains(other_entity) {
        println!("Player {other_entity} stepped on pressure plate {pressure_plate}");
    }
}

A collision event reader system before:

fn print_started_collisions(mut collision_reader: EventReader<CollisionStarted>) {
    for CollisionStarted(collider1, collider2) in collision_reader.read() {
        println!("{collider1} and {collider2} started colliding");
    }
}

and after:

fn print_started_collisions(mut collision_reader: MessageReader<CollisionStart>) {
    // Note: The event now also stores `body1` and `body2`
    for event in collision_reader.read() {
        println!("{} and {} started colliding", event.collider1, event.collider2);
    }
}

System Sets

System sets have been renamed to follow the new FooSystems naming convention.

  • PhysicsSetPhysicsSystems
  • PhysicsStepSetPhysicsStepSystems
  • SubstepSetSubstepSystems
  • SubstepSolverSetSubstepSolverSystems
  • SolverSetSolverSystems
  • IntegrationSetIntegrationSystems
  • BroadPhaseSetBroadPhaseSystems
  • NarrowPhaseSetNarrowPhaseSystems
  • SweptCcdSetSweptCcdSystems
  • PhysicsTransformSetPhysicsTransformSystems

ColliderConstructorHierarchy

Bevy 0.17 changed the way Name works for glTF mesh primitives (migration guide). Instead of MeshName.PrimitiveIndex, it is now in the form of MeshName.MaterialName. This also means that APIs such as ColliderConstructorHierarchy::with_constructor_for_name now use this format.

ColliderConstructorHierarchy::new(ColliderConstructor::ConvexDecompositionFromMesh)
    .with_density_for_name("armL_mesh.ferris_material", 3.0)
    .with_density_for_name("armR_mesh.ferris_material", 3.0)

Force Overhaul #770

Avian 0.4 overhauls the force APIs, and removes the ExternalForce, ExternalTorque, ExternalImpulse, and ExternalAngularImpulse components.

  • For persistent forces and torques, use the new ConstantForce and ConstantTorque components.
  • For non-persistent forces that get cleared automatically, use the new Forces helper QueryData.
  • Impulses can no longer be persistent. Use persistent forces instead.

The new ForcePlugin must be enabled for forces to function properly. It is included in PhysicsPlugins by default.

Joints #517, #735, #799, #803

Avian 0.4 contains a lot of changes and improvements for joints.

Core APIs

  • Joint APIs are now in dynamics::joints instead of dynamics::solver::joints
  • The Joint trait has been removed in favor of the EntityConstraint trait and helper methods on the joint types themselves
  • Renamed entity1 and entity2 to body1 and body2
  • Renamed free_axis to slider_axis for PrismaticJoint
  • Renamed aligned_axis to hinge_axis for RevoluteJoint
  • Renamed with_local_anchor_1, with_local_anchor_2, local_anchor_1, and local_anchor_2 to with_local_anchor1, with_local_anchor2, local_anchor1, and local_anchor2
  • The local_anchor1 and local_anchor2 methods now return an Option
  • The FixedJoint, PrismaticJoint, RevoluteJoint, and SphericalJoint now store a full JointFrame (anchor + basis) for each body instead of just local anchors
  • Removed swing_axis from SphericalJoint; just set the twist_axis, and the swing limit cone will be oriented accordingly
  • Removed damping properties and methods from joint types in favor of the JointDamping component
  • Removed force properties and methods from joint types in favor of the JointForces component
  • Each part of a joint has its own compliance and helpers for it, such as with_point_compliance and with_swing_compliance.

Only One Joint Per Entity

Entities can now only hold up to one type of joint component. If a joint is added on an entity that already has a joint, the old joint is automatically removed, and a warning is emitted if debug_assertions are enabled. A rigid body can still be attached to other bodies by multiple joints, but each joint must be on its own entity.

ContactEdge now also stores the rigid body entities.

Remove DistanceJoint::rest_length

The rest_length property of DistanceJoint has been removed in favor of just using length_limits.

  • Replace DistanceJoint::with_rest_length(1.0) with DistanceJoint::with_limits(1.0, 1.0).
  • Replace joint.rest_length = 1.0 with joint.length_limits = 1.0.into().

Solver Reorganization and XPBD

  • XPBD logic is now contained within dynamics::solver::xpbd, gated behind the xpbd_joints feature
  • XPBD system sets from SubstepSolverSet have been extracted to a separate XpbdSolverSystems enum
  • XPBD systems are now initialized by an XpbdSolverPlugin

Custom XPBD Constraints

  • The XpbdConstraint trait now has a prepare step to prepare base translational and rotational offsets and any other pre-step data.
  • XpbdConstraint now has a SolverData associated type for a solver data component implementing the XpbdConstraintSolverData trait. This is taken by prepare and solve.
  • XpbdConstraint::solve and many related methods now use SolverBody and SolverBodyInertia structs. Positional corrections are applied to the delta_position and delta_rotation properties. Updated positional information can be computed based on the pre-step data and these deltas.
  • apply_positional_lagrange_update has been removed. Use apply_positional_impulse instead.
  • xpbd::solve_constraint is now xpbd::solve_xpbd_joint, and only supports two entities (make your own system if you need more).
  • Most methods that previously returned forces or torques now return Lagrange multiplier updates.
  • See the custom_constraint example for a functional demonstration of implementing a custom constraint.

Contact APIs #771, #788

Contact Impulses

ContactPoint::normal_impulse previously corresponded to the clamped accumulated normal impulse from the last substep, used for warm starting the contact solver. It did not represent the total impulse applied across substeps and restitution, despite the ambiguous name.

Now, ContactPoint::normal_impulse works like you would expect, and represents the total normal impulse applied at a contact point. Divide by the time step to get the corresponding force.

The old warm starting impulses are now stored as warm_start_normal_impulse and warm_start_tangent_impulse (previously tangent_impulse).

The method APIs such as total_normal_impulse, total_normal_impulse_magnitude, and max_normal_impulse have been updated accordingly to use the new normal_impulse. Additionally, ContactPair::max_normal_impulse has be...

Read more

v0.3.1

Choose a tag to compare

@Jondolf Jondolf released this 05 Jun 09:11

What's Changed

  • Fix body property of collision events and reflect CollisionEventsEnabled properly by @Jondolf in #752

Full Changelog: v0.3.0...v0.3.1

Avian v0.3.0

Choose a tag to compare

@Jondolf Jondolf released this 09 May 22:33
2d27900

Avian Physics 0.3 has been released! 🪶

Avian 0.3 cover image

Highlights

Avian 0.3 is another huge release, with several new features, quality-of-life improvements, and important bug fixes. Highlights include:

  • Opt-in contact reporting: Collision events are now only sent for entities that have the CollisionEventsEnabled component, reducing unwanted overhead and iteration.
  • Observable collision events: Observers finally support collision events, making it easy to define per-entity collision handlers.
  • Collision hooks: Users can "hook into" the collision pipeline, making it possible to efficiently filter and modify contacts.
  • Per-manifold material properties: Friction, restitution, and tangent velocity can be modified for contact manifolds, allowing the simulation of non-uniform materials and conveyor belts.
  • Collider context: Custom colliders that implement AnyCollider have a Context for ECS access.
  • Physics diagnostics: Avian has built-in diagnostics and a debug UI for runtime physics profiling.
  • Reworked contact pair management: Contacts have been massively reworked to reduce allocations and unnecessary work while increasing parallelism.
  • Faster collisions and spatial queries: Collisions and spatial queries have much less overhead.
  • Bevy 0.16 support: Avian has been updated to the latest version of Bevy, and is taking advantage of relationships for attaching colliders to rigid bodies.

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

Collision Hooks #610

The BroadPhasePlugin, NarrowPhasePlugin, and many NarrowPhase methods now take generics for CollisionHooks. If you have no collision hooks, you can use ().

Physics Picking #632

The RenderLayers of cameras and collider entities no longer affect physics picking. Add the new PhysicsPickingFilter component to cameras to control which CollisionLayers and colliders are included in picking.

Default Layers for ColliderConstructorHierarchy #649

ColliderConstructorHierarchy now defaults to one membership (the first layer) and all filters for the CollisionLayers of generated colliders. This is consistent with how the CollisionLayers component already works normally.

Previously, it was still using the old default of all memberships and all filters.

Improved Contact Types #616 #685

There have been several changes to Avian's contact types to make them more optimized and clear.

Contacts

  • Contacts has been renamed to ContactPair.
  • The total_normal_impulse property has been replaced with a total_normal_impulse helper method.
  • The total_normal_force helper has been deprecated. Instead, just divide the impulse by the substep timestep.
  • The total_tangent_impulse property and total_friction_force helper have been removed for being inaccurate/misleading. The tangent impulse magnitudes of each individual point can still be accessed.

ContactManifold

  • ContactManifold::contacts has been renamed to ContactManifold::points.
  • The local normal1 and normal2 have been replaced with a single world-space normal, pointing from the first shape to the second.

ContactData

  • ContactData has been renamed to ContactPoint, since it specifically represents a point in a contact manifold, not general contact data.
  • point1 and point2 have been renamed to local_point1 and local_point2 for explicitness.
  • normal1 and normal2 have been removed, since the normal is already stored in the ContactManifold.

Add Context to AnyCollider #665

  • AnyCollider implementors now need to specify a Context associated SystemParam. If this is unnecessary, () should be used.
  • When trying to use methods from AnyCollider on an implementation with () context, SimpleCollider should be used instead.
  • Methods on AnyCollider have been suffixed with _with_context.

Bevy 0.16 Support #670

Avian now uses Bevy 0.16.

The AncestorMarkerPlugin no longer requires a schedule or system set.

Change ColliderParent to ColliderOf relationship #671

The ColliderParent component has been renamed to ColliderOf, and it is now a Relationship. The ColliderHierarchyPlugin (included in PhysicsPlugins) must be enabled for colliders to be automatically attached to rigid bodies, but ColliderOf can also be inserted manually otherwise.

The transform management in ColliderHierarchyPlugin has been extracted into a new ColliderTransformPlugin. The ColliderHierarchyPlugin no longer takes a schedule.

Reworked Contact Pair Management #683

Avian's collision detection pipelines and contact pair management have been massively reworked for better performance and robustness.

PostProcessCollisions

The PostProcessCollisions schedule and NarrowPhaseSet::PostProcess system set have been removed, as it is incompatible with new optimizations to narrow phase collision detection. Instead, use CollisionHooks for contact modification.

Contact Reporting

The ContactReportingPlugin and PhysicsStepSet::ReportContacts system set have been removed. Contact reporting is now handled by the NarrowPhasePlugin directly.

The Collision event no longer exists. Instead, use Collisions directly, or get colliding entities using the CollidingEntities component.

The CollisionStarted and CollisionEnded events are now only sent if either entity in the collision has the CollisionEventsEnabled component. If you'd like to revert to the old behavior of having collision events for all entities, consider making CollisionEventsEnabled a required component for Collider:

app.register_required_components::<Collider, CollisionEventsEnabled>();

Collisions

The Collisions resource is now a SystemParam.

// Old
fn iter_collisions(collisions: Res<Collisions>) {
    todo!()
}

// New
fn iter_collisions(collisions: Collisions) {
    todo!()
}

Internally, Collisions now stores a ContactGraph that stores both touching and non-touching contact pairs. The Collisions system parameter is just a wrapper that provides a simpler API and only returns touching contacts.

The collisions_with_entity method has also been renamed to collisions_with, and all methods that mutatate, add, or remove contact pairs have been removed from Collisions. However, the following mutating methods are available on ContactGraph:

  • get_mut
  • iter_mut
  • iter_touching_mut
  • collisions_with_mut
  • add_pair/add_pair_with_key
  • insert_pair/insert_pair_with_key
  • remove_pair
  • remove_collider_with

For most scenarios, contact modification and removal are intended to be handled with CollisionHooks.

ContactPair (previously Contacts)

The during_current_frame and during_previous_frame properties of ContactPair have been removed in favor of a flags property storing information in a more compact bitflag format. The is_sensor, is_touching, collision_started, and collision_ended helper methods can be used instead.

ContactManifold

Methods such as AnyCollider::contact_manifolds_with_context now take &mut Vec<ContactManifold> instead of returning a new vector every time. This allows manifolds to be persisted more effectively, and reduces unnecessary allocations.

BroadCollisionPairs

The BroadCollisionPairs resource has been removed. Use the ContactGraph resource instead.

AabbIntersections

The AabbIntersections component has been removed. Use ContactGraph::entities_colliding_with instead.

Change CollisionLayers to a Required Component #693

CollisionLayers is now a required component for colliders and is inserted automatically. Collision detection may not work properly without it.

Reorganize Collision Detection Modules and Re-Exports #698

Some collision detection modules and imports have been reorganized.

The following modules have been moved:

  • layers from collision to collision::collider
  • contact_query from collision to collision::collider::parry
  • feature_id from collision to collision::contact_types

Previously, a lot of collision detection types were also re-exported directly from the collision module. Now, there is instead a prelude for the collision module.

Contact Constraint Generation System Ordering #699

NarrowPhaseSet::GenerateConstraints has been removed. Contact constraints are now generated as part of NarrowPhaseSet::Update.

Rename Entity Properties #718 #719

  • ContactPair: The entity1 and entity2 properties are now collider1 and collider2, and body_entity1 and body_entity2 are now body1 and body2.
  • ContactConstraint: The entity1 and entity2 properties are now body1 and body2, and collider_entity1 and collider_entity2 are now collider1 and collider2.
  • ColliderQuery: The rigid_body property has been renamed to of (for ColliderOf) and there is a new body helper to get the contained entity directly.

What's Changed

  • Collision Hooks @Jondolf in #610
  • Fix collisions not being cleared for immediately despawned entities by @Jondolf in #642
  • Introduce PhysicsPickingFilter by @morgenthum in #632
  • Remove unnecessary cfg_attr from from_shape mass helpers by @jondol...
Read more

v0.2.1

Choose a tag to compare

@Jondolf Jondolf released this 26 Jan 14:22

What's Changed

New Contributors

Full Changelog: v0.2.0...v0.2.1