Skip to content

Latest commit

 

History

History
269 lines (177 loc) · 14.6 KB

File metadata and controls

269 lines (177 loc) · 14.6 KB

Migrating From v0.3 to v0.4

Bevy 0.17

PRs: #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

PRs: #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

PRs: #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

PRs: #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 been split into ContactPair::max_normal_impulse (returns a vector) and ContactPair::max_normal_impulse_magnitude (returns a scalar).

The normal_force and tangent_force methods of ContactPoint have been removed.

ContactConstraintPoint::max_normal_impulse is now stored in the ContactNormalPart as total_impulse.

Contact Points

The local_point1 and local_point2 properties of ContactPoint have been removed in favor of a world-space anchor1 and anchor2 relative to the center of mass.

The global_point1 and global_point2 methods have also been removed, but a new world-space point is available for the midpoint between the closest points.

Contact Graph

  • The ContactGraph now stores ContactEdges in the graph, containing only edge connectivity information with stable ContactIds.
  • The ContactGraph now stores ContactPairs in separate active_pairs and sleeping_pairs lists.
  • iter and iter_mut have been renamed to iter_active and iter_active_mut / iter_sleeping and iter_sleeping_mut.
  • iter_touching and iter_touching_mut have been renamed to iter_touching_active and iter_touching_active_mut / iter_touching_sleeping and iter_touching_sleeping_mut.
  • collisions_with has been renamed to contact_pairs_with.
  • collisions_with_mut has been removed for now.
  • add_pair has been replaced by add_edge, and add_pair_with_key has been replaced by add_edge_and_key_with.
  • insert_pair and insert_pair_with have been removed. Add or update pairs manually instead.
  • remove_pair has been renamed to remove_edge.

Contact Pairs

  • ContactPair now stores the ContactId associated with the ContactEdge in the ContactGraph. It must be provided to ContactPair::new. It is initialized automatically by calls to methods like ContactGraph::add_edge.
  • ContactPairFlags no longer stores whether CONTACT_EVENTS are enabled. It is instead stored on ContactEdgeFlags.
  • ContactManifold no longer stores the index of the manifold.

Sleeping and Simulation Islands

PRs: #809

Stacks of bodies as well as bodies connected by joints now form "simulation islands" that are allowed to enter a low-cost sleeping state when all bodies in a given island are resting. This can significantly reduce CPU overhead for large game worlds with lots of dynamic bodies. Previously, bodies were only allowed to sleep when they were not interacting with other dynamic bodies.

The following components have been renamed:

  • TimeSleeping -> SleepTimer
  • SleepingThreshold -> SleepThreshold
  • DeactivationTime -> TimeToSleep (also a component and not a resource now)

Additionally, the SleepingPlugin has been replaced by the IslandSleepingPlugin.

Solver Bodies

PRs: #735

Avian's solver now uses special SolverBody and SolverBodyInertia components instead of separate components like Position, Rotation, AccumulatedTranslation, LinearVelocity, and AngularVelocity. They are initialized for awake dynamic and kinematic bodies in the substepping loop, and the results are written back to the user-facing components at the end. This also means that if you are running custom logic inside the substepping loop, you should generally use SolverBody instead of the separate components.

Solver bodies were added to drastically improve the performance of the solver, but it also means significant changes to internals.

Removed Components and Properties

The following components have been removed and are no longer stored for rigid bodies:

  • AccumulatedTranslation
  • PreSolveAccumulatedTranslation (now called PreSolveDeltaPosition)
  • PreSolveLinearVelocity
  • PreSolveAngularVelocity
  • PreSolveRotation
  • PreviousRotation

A new PreSolveDeltaRotation component has also been added.

The current_position helper on RigidBodyQueryItem and ColliderQueryItem has been removed.

The local_anchor1 and local_anchor2 properties on ContactConstraintPoint have been removed.

Other

  • SolverSet::ApplyTranslation has been renamed to SolverSystems::Finalize.

Physics Transforms and PreparePlugin

PRs: #760, #785

  • Position, Rotation, and ColliderAabb are now initialized with correct world-space values right after spawn.
  • The SyncPlugin has been renamed to PhysicsTransformPlugin, and SyncSet has been renamed to PhysicsTransformSystems.
  • The PreparePlugin and PrepareSet have been removed. Use PhysicsSet::Prepare for preparation logic, and run it after PhysicsTransformSystems::TransformToPosition if it must run after transforms have been applied to physics positions.
  • Logic inside the PhysicsSchedule can no longer use Transform. Use Position and Rotation instead.
  • PhysicsSet::Sync has been renamed to PhysicsSet::Writeback.
  • SyncConfig has been renamed to PhysicsTransformConfig.

Symmetric 3x3 Matrix for Angular Inertia

PRs: #777

In 3D, AngularInertia and ComputedAngularInertia APIs now use a SymmetricMat3 from glam_natrix_extras instead of the old Mat3 for the angular inertia tensor. AngularInertia has new constructors like try_from_mat3 and from_mat3_unchecked to use Mat3 directly.

The GlobalAngularInertia component has been removed. You can compute the rotated angular inertia tensor using ComputedAngularInertia::rotated.

Debug Rendering

PRs: #829

The PhysicsDebugPlugin now always runs in PostUpdate. Replace calls to PhysicsDebugPlugin::new(SomeSchedule) with PhysicsDebugPlugin or PhysicsDebugPlugin::default().

Additionally, debug rendering now uses GlobalTransform instead of Position and Rotation. This allows debug rendering to use interpolated transforms if TransformInterpolation is used.

Fallible Trimesh Colliders

PRs: #761

Collider::trimesh and Collider::trimesh_with_config can now panic for degenerate input. Use Collider::try_trimesh and Collider::try_trimesh_with_config to instead get a Result and handle error cases manually.

Remove ColliderQuery

PRs: #775

The ColliderQuery QueryData type no longer exists. Query for the components you need manually, or define your own QueryData type.