avian3d/lib.rs
1//! 
2//!
3//! **Avian** is an ECS-driven 2D and 3D physics engine for the [Bevy game engine](https://bevyengine.org/).
4//!
5//! Check out the [GitHub repository](https://github.com/Jondolf/avian)
6//! for more information about the design, read the [Getting Started](#getting-started)
7//! guide below to get up to speed, and take a look at the [Table of Contents](#table-of-contents)
8//! for an overview of the engine's features and their documentation.
9//!
10//! You can also check out the [FAQ](#frequently-asked-questions), and if you encounter
11//! any further problems, consider saying hello on the [Bevy Discord](https://discord.gg/bevy)!
12//!
13//! # Getting Started
14//!
15//! This short guide should help you get started with Avian.
16//!
17//! ## Add the Dependency
18//!
19//! First, add `avian2d` or `avian3d` to the dependencies in your `Cargo.toml`:
20//!
21//! ```toml
22//! # For 2D applications:
23//! [dependencies]
24//! avian2d = "0.3"
25//!
26//! # For 3D applications:
27//! [dependencies]
28//! avian3d = "0.3"
29//!
30//! # If you want to use the most up-to-date version, you can follow the main branch:
31//! [dependencies]
32//! avian3d = { git = "https://github.com/Jondolf/avian", branch = "main" }
33//! ```
34//!
35//! You can specify features by disabling the default features and manually adding
36//! the feature flags you want:
37//!
38//! ```toml
39//! [dependencies]
40//! # Add 3D Avian with double-precision floating point numbers.
41//! # `parry-f64` enables collision detection using Parry.
42//! avian3d = { version = "0.3", default-features = false, features = ["3d", "f64", "parry-f64"] }
43//! ```
44//!
45//! ## Feature Flags
46//!
47//! | Feature | Description | Default feature |
48//! | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
49//! | `2d` | Enables 2D physics. Incompatible with `3d`. | Yes (`avian2d`) |
50//! | `3d` | Enables 3D physics. Incompatible with `2d`. | Yes (`avian3d`) |
51//! | `f32` | Enables `f32` precision for physics. Incompatible with `f64`. | Yes |
52//! | `f64` | Enables `f64` precision for physics. Incompatible with `f32`. | No |
53//! | `default-collider` | Enables the default [`Collider`]. Required for [spatial queries](spatial_query). Requires either the `parry-f32` or `parry-f64` feature. | Yes |
54//! | `parry-f32` | Enables the `f32` version of the Parry collision detection library. Also enables the `default-collider` feature. | Yes |
55//! | `parry-f64` | Enables the `f64` version of the Parry collision detection library. Also enables the `default-collider` feature. | No |
56#![cfg_attr(
57 feature = "3d",
58 doc = "| `collider-from-mesh` | Allows you to create [`Collider`]s from `Mesh`es. | Yes |"
59)]
60//! | `bevy_scene` | Enables [`ColliderConstructorHierarchy`] to wait until a [`Scene`] has loaded before processing it. | Yes |
61//! | `bevy_picking` | Enables physics picking support for [`bevy_picking`] using the [`PhysicsPickingPlugin`]. The plugin must be added separately. | Yes |
62//! | `bevy_diagnostic` | Enables writing [physics diagnostics] to the [`DiagnosticsStore`] with the [`PhysicsDiagnosticsPlugin`]. The plugin must be added separately. | No |
63//! | `diagnostic_ui` | Enables [physics diagnostics] UI for performance timers and counters using the [`PhysicsDiagnosticsUiPlugin`]. The plugin must be added separately. | No |
64//! | `debug-plugin` | Enables physics debug rendering using the [`PhysicsDebugPlugin`]. The plugin must be added separately. | Yes |
65//! | `enhanced-determinism` | Enables cross-platform deterministic math, improving determinism across architectures at a small performance cost. | No |
66//! | `parallel` | Enables some extra multithreading, which improves performance for larger simulations but can add some overhead for smaller ones. | Yes |
67//! | `simd` | Enables [SIMD] optimizations. | No |
68//! | `serialize` | Enables support for serialization and deserialization using Serde. | No |
69//!
70//! [`bevy_picking`]: bevy::picking
71//! [physics diagnostics]: diagnostics
72//! [`DiagnosticsStore`]: bevy::diagnostic::DiagnosticsStore
73//! [SIMD]: https://en.wikipedia.org/wiki/Single_instruction,_multiple_data
74//!
75//! ## Add the Plugins
76//!
77//! Avian is designed to be very modular. It is built from several [plugins](PhysicsPlugins) that
78//! manage different parts of the engine. These plugins can be easily initialized and configured through
79//! the [`PhysicsPlugins`] plugin group.
80//!
81//! ```no_run
82#![cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
83#![cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
84//! use bevy::prelude::*;
85//!
86//! fn main() {
87//! App::new()
88//! .add_plugins((DefaultPlugins, PhysicsPlugins::default()))
89//! // ...your other plugins, systems and resources
90//! .run();
91//! }
92//! ```
93//!
94//! Now you can use all of Avian's components and resources to build whatever you want!
95//!
96//! For example, adding a [rigid body](RigidBody) with a [collider](Collider) is as simple as spawning an entity
97//! with the [`RigidBody`] and [`Collider`] components:
98//!
99//! ```
100#![cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
101#![cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
102//! use bevy::prelude::*;
103//!
104//! fn setup(mut commands: Commands) {
105#![cfg_attr(
106 feature = "2d",
107 doc = " commands.spawn((RigidBody::Dynamic, Collider::circle(0.5)));"
108)]
109#![cfg_attr(
110 feature = "3d",
111 doc = " commands.spawn((RigidBody::Dynamic, Collider::sphere(0.5)));"
112)]
113//! }
114//! ```
115//!
116//! You can find lots of [usage examples](https://github.com/Jondolf/avian#more-examples)
117//! in the project's [repository](https://github.com/Jondolf/avian).
118//!
119//! # Table of Contents
120//!
121//! Below is a structured overview of the documentation for the various
122//! features of the engine.
123//!
124//! ## Rigid Body Dynamics
125//!
126//! - [Rigid body types](RigidBody#rigid-body-types)
127//! - [Creating rigid bodies](RigidBody#creation)
128//! - [Movement](RigidBody#movement)
129//! - [Linear](LinearVelocity) and [angular](AngularVelocity) velocity
130//! - [Forces](ExternalForce), [torque](ExternalTorque), and [linear](ExternalImpulse) and [angular](ExternalAngularImpulse) impulses
131//! - [Gravity] and [gravity scale](GravityScale)
132//! - [Mass properties](dynamics::rigid_body::mass_properties)
133//! - [Linear](LinearDamping) and [angular](AngularDamping) velocity damping
134//! - [Lock translational and rotational axes](LockedAxes)
135//! - [Dominance]
136//! - [Continuous Collision Detection (CCD)](dynamics::ccd)
137//! - [Speculative collision](dynamics::ccd#speculative-collision)
138//! - [Swept CCD](dynamics::ccd#swept-ccd)
139//! - [`Transform` interpolation and extrapolation](PhysicsInterpolationPlugin)
140//! - [Temporarily disabling a rigid body](RigidBodyDisabled)
141//! - [Automatic deactivation with sleeping](Sleeping)
142//!
143//! See the [`dynamics`] module for more details about rigid body dynamics in Avian.
144//!
145//! ## Collision Detection
146//!
147//! - [Colliders](Collider)
148//! - [Creation](Collider#creation)
149//! - [Density](ColliderDensity)
150//! - [Friction] and [restitution](Restitution) (bounciness)
151//! - [Collision layers](CollisionLayers)
152//! - [Sensors](Sensor)
153#![cfg_attr(
154 feature = "3d",
155 doc = "- Generating colliders for meshes and scenes with [`ColliderConstructor`] and [`ColliderConstructorHierarchy`]"
156)]
157//! - [Get colliding entities](CollidingEntities)
158//! - [Collision events](collision#collision-events)
159//! - [Accessing collision data](Collisions)
160//! - [Filtering and modifying contacts with hooks](CollisionHooks)
161//! - [Manual contact queries](collision::collider::contact_query)
162//! - [Temporarily disabling a collider](ColliderDisabled)
163//!
164//! See the [`collision`] module for more details about collision detection and colliders in Avian.
165//!
166//! ## Constraints and Joints
167//!
168//! - [Joints](dynamics::solver::joints)
169//! - [Fixed joint](FixedJoint)
170//! - [Distance joint](DistanceJoint)
171//! - [Prismatic joint](PrismaticJoint)
172//! - [Revolute joint](RevoluteJoint)
173#")]
174//! - [Temporarily disabling a joint](JointDisabled)
175//! - [Custom XPBD constraints](dynamics::solver::xpbd#constraints) (advanced)
176//!
177//! Joint motors and articulations are not supported yet, but they will be implemented in a future release.
178//!
179//! ## Spatial Queries
180//!
181//! - [Spatial query types](spatial_query)
182//! - [Raycasting](spatial_query#raycasting) and [`RayCaster`]
183//! - [Shapecasting](spatial_query#shapecasting) and [`ShapeCaster`]
184//! - [Point projection](spatial_query#point-projection)
185//! - [Intersection tests](spatial_query#intersection-tests)
186//! - [Spatial query filters](SpatialQueryFilter)
187//! - [The `SpatialQuery` system parameter](SpatialQuery)
188//!
189//! ## Configuration
190//!
191//! - [Gravity]
192//! - [`Transform` interpolation and extrapolation](PhysicsInterpolationPlugin)
193//! - [Physics speed](Physics#physics-speed)
194//! - [Configure simulation fidelity with substeps](SubstepCount)
195//!
196//! ## Debugging and Profiling
197//!
198//! - [Physics debug rendering](PhysicsDebugPlugin)
199//! - [Physics diagnostics](diagnostics)
200//!
201//! ## Scheduling
202//!
203//! - [Schedules and sets](PhysicsSchedulePlugin#schedules-and-sets)
204//! - [`PhysicsSet`]
205//! - [`PhysicsSchedule`] and [`PhysicsStepSet`]
206//! - [`SubstepSchedule`]
207//! - [`SolverSet`] and [`SubstepSolverSet`](dynamics::solver::schedule::SubstepSolverSet)
208//! - [`PrepareSet`](prepare::PrepareSet)
209//! - Many more internal system sets
210//! - [Configure the schedule used for running physics](PhysicsPlugins#custom-schedule)
211//! - [Pausing, resuming and stepping physics](Physics#pausing-resuming-and-stepping-physics)
212//! - [Usage on servers](#can-the-engine-be-used-on-servers)
213//!
214//! ## Architecture
215//!
216//! - [List of plugins and their responsibilities](PhysicsPlugins)
217//! - Extending and modifying the engine
218//! - [Custom plugins](PhysicsPlugins#custom-plugins)
219//! - [Custom XPBD constraints](dynamics::solver::xpbd#custom-constraints)
220//! - [Custom joints](dynamics::solver::joints#custom-joints)
221//!
222//! # Frequently Asked Questions
223//!
224//! - [How does Avian compare to Rapier and bevy_rapier?](#how-does-avian-compare-to-rapier-and-bevy_rapier)
225//! - [Why is nothing happening?](#why-is-nothing-happening)
226//! - [Why is everything moving so slowly?](#why-is-everything-moving-so-slowly)
227//! - [Why did my rigid body suddenly vanish?](#why-did-my-rigid-body-suddenly-vanish)
228//! - [Why is performance so bad?](#why-is-performance-so-bad)
229//! - [Why does movement look choppy?](#why-does-movement-look-choppy)
230//! - [Is there a character controller?](#is-there-a-character-controller)
231//! - [Why are there separate `Position` and `Rotation` components?](#why-are-there-separate-position-and-rotation-components)
232//! - [Can the engine be used on servers?](#can-the-engine-be-used-on-servers)
233//! - [Something else?](#something-else)
234//!
235//! ## How does Avian compare to Rapier and bevy_rapier?
236//!
237//! Rapier is the biggest and most used physics engine in the Rust ecosystem, and it is currently
238//! the most mature and feature-rich option.
239//!
240//! `bevy_rapier` is a great physics integration for Bevy, but it does have several problems:
241//!
242//! - It has to maintain a separate physics world and synchronize a ton of data with Bevy each frame
243//! - The source code is difficult to inspect, as the vast majority of it is glue code and wrappers
244//! for Bevy
245//! - It has poor docs.rs documentation, and the documentation on rapier.rs is often outdated and
246//! missing features
247//! - It is hard to extend as it's not very modular or composable in design
248//! - Overall, it doesn't have a native ECS-like feel outside of its public API
249//!
250//! Avian on the other hand is built *for* Bevy *with* Bevy, and it uses the ECS for both the internals
251//! and the public API. This removes the need for a separate physics world, reduces overhead, and makes
252//! the source code much more approachable and easy to inspect for Bevy users.
253//!
254//! In part thanks to Bevy's modular architecture and the ECS, Avian is also highly composable,
255//! as it consists of several independent plugins and provides lots of options for configuration and extensions,
256//! from [custom schedules](PhysicsPlugins#custom-schedule) and [plugins](PhysicsPlugins#custom-plugins) to
257//! [custom joints](dynamics::solver::joints#custom-joints) and [constraints](dynamics::solver::xpbd#custom-constraints).
258//!
259//! One disadvantage of Avian is that it is still relatively young, so it can have more bugs,
260//! some missing features, and fewer community resources and third party crates. However, it is growing quite
261//! rapidly, and it is already pretty close to feature-parity with Rapier.
262//!
263//! At the end of the day, both engines are solid options. If you are looking for a more mature and tested
264//! physics integration, `bevy_rapier` is the better choice, but if you prefer an engine with less overhead
265//! and a more native Bevy integration, consider using Avian. Their core APIs are also quite similar,
266//! so switching between them shouldn't be too difficult.
267//!
268//! ## Why is nothing happening?
269//!
270//! Make sure you have added the [`PhysicsPlugins`] plugin group and you have given your rigid bodies
271//! a [`RigidBody`] component. See the [getting started](#getting-started) section.
272//!
273//! ## Why is everything moving so slowly?
274//!
275//! If your application is in 2D, you might be using pixels as length units. This will require you to use
276//! larger velocities and forces than you would in 3D. Make sure you set [`Gravity`] to some larger value
277//! as well, because its magnitude is `9.81` by default, which is tiny in pixels.
278//!
279//! ## Why is performance so bad?
280//!
281//! Make sure you are building your project in release mode using `cargo build --release`.
282//!
283//! You can further optimize builds by setting the number of codegen units in your `Cargo.toml` to 1,
284//! although this will also increase build times.
285//!
286//! ```toml
287//! [profile.release]
288//! codegen-units = 1
289//! ```
290//!
291//! ## Why does movement look choppy?
292//!
293//! To produce consistent, frame rate independent behavior, physics by default runs
294//! in the [`FixedPostUpdate`] schedule with a fixed timestep, meaning that the time between
295//! physics ticks remains constant. On some frames, physics can either not run at all or run
296//! more than once to catch up to real time. This can lead to visible stutter for movement.
297//!
298//! This stutter can be resolved by *interpolating* or *extrapolating* the positions of physics objects
299//! in between physics ticks. Avian has built-in support for this through the [`PhysicsInterpolationPlugin`],
300//! which is included in the [`PhysicsPlugins`] by default.
301//!
302//! Interpolation can be enabled for an individual entity by adding the [`TransformInterpolation`] component:
303//!
304//! ```
305#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
306#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
307//! # use bevy::prelude::*;
308//! #
309//! fn setup(mut commands: Commands) {
310//! // Enable interpolation for this rigid body.
311//! commands.spawn((
312//! RigidBody::Dynamic,
313//! Transform::default(),
314//! TransformInterpolation,
315//! ));
316//! }
317//! ```
318//!
319//! To make *all* rigid bodies interpolated by default, use [`PhysicsInterpolationPlugin::interpolate_all()`]:
320//!
321//! ```no_run
322#![cfg_attr(feature = "2d", doc = "# use avian2d::prelude::*;")]
323#![cfg_attr(feature = "3d", doc = "# use avian3d::prelude::*;")]
324//! # use bevy::prelude::*;
325//! #
326//! fn main() {
327//! App::new()
328//! .add_plugins(PhysicsPlugins::default().set(PhysicsInterpolationPlugin::interpolate_all()))
329//! // ...
330//! .run();
331//! }
332//! ```
333//!
334//! See the [`PhysicsInterpolationPlugin`] for more information.
335//!
336//! If this does not fix the choppiness, the problem could also be related to system ordering.
337//! If you have a system for camera following, make sure it runs *after* physics,
338//! but *before* Bevy's transform propagation in `PostUpdate`.
339//!
340//! ```
341//! # use bevy::prelude::*;
342//! #
343//! # let mut app = App::new();
344//! #
345//! app.add_systems(
346//! PostUpdate,
347//! camera_follow_player.before(TransformSystem::TransformPropagate),
348//! );
349//! #
350//! # fn camera_follow_player() {}
351//! ```
352//!
353//! ## Is there a character controller?
354//!
355//! Avian does not have a built-in character controller, so if you need one,
356//! you will need to implement it yourself. However, third party character controllers
357//! like [`bevy_tnua`](https://github.com/idanarye/bevy-tnua) support Avian, and [`bevy_mod_wanderlust`](https://github.com/PROMETHIA-27/bevy_mod_wanderlust)
358//! and others are also likely to get Avian support soon.
359//!
360//! For custom character controllers, you can take a look at the
361#![cfg_attr(
362 feature = "2d",
363 doc = "[`dynamic_character_2d`] and [`kinematic_character_2d`] examples to get started."
364)]
365#![cfg_attr(
366 feature = "3d",
367 doc = "[`dynamic_character_3d`] and [`kinematic_character_3d`] examples to get started."
368)]
369//!
370#![cfg_attr(
371 feature = "2d",
372 doc = "[`dynamic_character_2d`]: https://github.com/Jondolf/avian/tree/main/crates/avian2d/examples/dynamic_character_2d
373[`kinematic_character_2d`]: https://github.com/Jondolf/avian/tree/main/crates/avian2d/examples/kinematic_character_2d"
374)]
375#![cfg_attr(
376 feature = "3d",
377 doc = "[`dynamic_character_3d`]: https://github.com/Jondolf/avian/tree/main/crates/avian3d/examples/dynamic_character_3d
378[`kinematic_character_3d`]: https://github.com/Jondolf/avian/tree/main/crates/avian3d/examples/kinematic_character_3d"
379)]
380//!
381//! ## Why are there separate `Position` and `Rotation` components?
382//!
383//! While `Transform` can be used for the vast majority of things, Avian internally
384//! uses separate [`Position`] and [`Rotation`] components. These are automatically
385//! kept in sync by the [`SyncPlugin`].
386//!
387//! There are several reasons why the separate components are currently used.
388//!
389//! - Position and rotation should be global from the physics engine's point of view.
390//! - Transform scale and shearing can cause issues and rounding errors in physics.
391//! - Transform hierarchies can be problematic.
392//! - There is no `f64` version of `Transform`.
393//! - There is no 2D version of `Transform` (yet), and having a 2D version can optimize several computations.
394//! - When position and rotation are separate, we can technically have more systems running in parallel.
395//! - Only rigid bodies have rotation, particles typically don't (although we don't make a distinction yet).
396//!
397//! In external projects however, using [`Position`] and [`Rotation`] is only necessary when you
398//! need to manage positions within [`PhysicsSet::StepSimulation`]. Elsewhere, you should be able to use `Transform`.
399//!
400//! There is also a possibility that we will revisit this if/when Bevy has a `Transform2d` component.
401//! Using `Transform` feels more idiomatic and simple, so it would be nice if it could be used directly
402//! as long as we can get around the drawbacks.
403//!
404//! ## Can the engine be used on servers?
405//!
406//! Yes! Networking often requires running the simulation in a specific schedule, and in Avian it is straightforward
407//! to [set the schedule that runs physics](PhysicsPlugins#custom-schedule) and [configure the timestep](Physics) if needed.
408//! By default, physics runs at a fixed timestep in [`FixedPostUpdate`].
409//!
410//! ## Something else?
411//!
412//! Physics engines are very large and Avian is young, so stability issues and bugs are to be expected.
413//!
414//! If you encounter issues, please consider first taking a look at the
415//! [issues on GitHub](https://github.com/Jondolf/avian/issues) and
416//! [open a new issue](https://github.com/Jondolf/avian/issues/new) if there already isn't one regarding your problem.
417//!
418//! You can also come and say hello on the [Bevy Discord server](https://discord.com/invite/gMUk5Ph).
419//! There, you can find an Avian Physics topic on the `#ecosystem-crates` channel where you can ask questions.
420//!
421//! # License
422//!
423//! Avian is free and open source. All code in the Avian repository is dual-licensed under either:
424//!
425//! - MIT License ([LICENSE-MIT](https://github.com/Jondolf/avian/blob/main/LICENSE-MIT)
426//! or <http://opensource.org/licenses/MIT>)
427//! - Apache License, Version 2.0 ([LICENSE-APACHE](https://github.com/Jondolf/avian/blob/main/LICENSE-APACHE)
428//! or <http://www.apache.org/licenses/LICENSE-2.0>)
429//!
430//! at your option.
431
432#![doc(
433 html_logo_url = "https://raw.githubusercontent.com/Jondolf/avian/avian/assets/branding/icon.png",
434 html_favicon_url = "https://raw.githubusercontent.com/Jondolf/avian/avian/assets/branding/icon.png"
435)]
436#![allow(
437 unexpected_cfgs,
438 clippy::type_complexity,
439 clippy::too_many_arguments,
440 rustdoc::invalid_rust_codeblocks
441)]
442#![warn(clippy::doc_markdown, missing_docs)]
443
444#[cfg(all(not(feature = "f32"), not(feature = "f64")))]
445compile_error!("either feature \"f32\" or \"f64\" must be enabled");
446
447#[cfg(all(feature = "f32", feature = "f64"))]
448compile_error!("feature \"f32\" and feature \"f64\" cannot be enabled at the same time");
449
450#[cfg(all(not(feature = "2d"), not(feature = "3d")))]
451compile_error!("either feature \"2d\" or \"3d\" must be enabled");
452
453#[cfg(all(feature = "2d", feature = "3d"))]
454compile_error!("feature \"2d\" and feature \"3d\" cannot be enabled at the same time");
455
456#[cfg(all(
457 feature = "default-collider",
458 feature = "f32",
459 not(feature = "parry-f32")
460))]
461compile_error!(
462 "feature \"default-collider\" requires the feature \"parry-f32\" when \"f32\" is enabled"
463);
464
465#[cfg(all(
466 feature = "default-collider",
467 feature = "f64",
468 not(feature = "parry-f64")
469))]
470compile_error!(
471 "feature \"default-collider\" requires the feature \"parry-f64\" when \"f64\" is enabled"
472);
473
474extern crate alloc;
475
476#[cfg(all(feature = "2d", feature = "parry-f32"))]
477pub extern crate parry2d as parry;
478
479#[cfg(all(feature = "2d", feature = "parry-f64"))]
480pub extern crate parry2d_f64 as parry;
481
482#[cfg(all(feature = "3d", feature = "parry-f32"))]
483pub extern crate parry3d as parry;
484
485#[cfg(all(feature = "3d", feature = "parry-f64"))]
486pub extern crate parry3d_f64 as parry;
487
488pub mod collision;
489#[cfg(feature = "debug-plugin")]
490pub mod debug_render;
491pub mod diagnostics;
492pub mod dynamics;
493pub mod interpolation;
494pub mod math;
495#[cfg(feature = "bevy_picking")]
496pub mod picking;
497pub mod position;
498pub mod prepare;
499pub mod schedule;
500pub mod spatial_query;
501pub mod sync;
502
503pub mod data_structures;
504
505mod type_registration;
506pub use type_registration::PhysicsTypeRegistrationPlugin;
507
508/// Re-exports common components, bundles, resources, plugins and types.
509pub mod prelude {
510 #[cfg(feature = "debug-plugin")]
511 pub use crate::debug_render::*;
512 #[cfg(feature = "diagnostic_ui")]
513 pub use crate::diagnostics::ui::{PhysicsDiagnosticsUiPlugin, PhysicsDiagnosticsUiSettings};
514 #[cfg(feature = "bevy_diagnostic")]
515 pub use crate::diagnostics::PhysicsDiagnosticsPlugin;
516 #[cfg(feature = "bevy_picking")]
517 pub use crate::picking::{
518 PhysicsPickable, PhysicsPickingFilter, PhysicsPickingPlugin, PhysicsPickingSettings,
519 };
520 #[cfg(feature = "default-collider")]
521 pub(crate) use crate::position::RotationValue;
522 pub use crate::{
523 collision::prelude::*,
524 dynamics::{self, ccd::SpeculativeMargin, prelude::*},
525 interpolation::*,
526 position::{Position, Rotation},
527 prepare::{init_transforms, PrepareConfig, PreparePlugin},
528 schedule::*,
529 spatial_query::{self, *},
530 sync::SyncPlugin,
531 type_registration::PhysicsTypeRegistrationPlugin,
532 PhysicsPlugins,
533 };
534 pub(crate) use crate::{
535 diagnostics::AppDiagnosticsExt,
536 math::*,
537 position::{PreSolveAccumulatedTranslation, PreSolveRotation, PreviousRotation},
538 };
539 pub use avian_derive::*;
540}
541
542mod utils;
543
544#[cfg(test)]
545mod tests;
546
547use bevy::{
548 app::PluginGroupBuilder,
549 ecs::{intern::Interned, schedule::ScheduleLabel, system::SystemParamItem},
550 prelude::*,
551};
552#[allow(unused_imports)]
553use prelude::*;
554
555/// A plugin group containing all of Avian's plugins.
556///
557/// # Plugins
558///
559/// By default, the following plugins will be added:
560///
561/// | Plugin | Description |
562/// | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
563/// | [`PhysicsSchedulePlugin`] | Sets up the physics engine by initializing the necessary schedules, sets and resources. |
564/// | [`PhysicsTypeRegistrationPlugin`] | Registers physics types to the `TypeRegistry` resource in `bevy_reflect`. |
565/// | [`PreparePlugin`] | Runs systems at the start of each physics frame. Initializes [rigid bodies](RigidBody) and updates components. |
566/// | [`MassPropertyPlugin`] | Manages mass properties of dynamic [rigid bodies](RigidBody). |
567/// | [`ColliderBackendPlugin`] | Handles generic collider backend logic, like initializing colliders and AABBs and updating related components. |
568/// | [`ColliderHierarchyPlugin`] | Manages [`ColliderOf`] relationships based on the entity hierarchy. |
569/// | [`ColliderTransformPlugin`] | Propagates and updates transforms for colliders. |
570/// | [`BroadPhasePlugin`] | Finds pairs of entities with overlapping [AABBs](ColliderAabb) to reduce the number of potential contacts for the [narrow phase](collision::narrow_phase). |
571/// | [`NarrowPhasePlugin`] | Manages contacts and generates contact constraints. |
572/// | [`SolverSchedulePlugin`] | Sets up the solver and substepping loop by initializing the necessary schedules, sets and resources. |
573/// | [`IntegratorPlugin`] | Handles motion caused by velocity, and applies external forces and gravity. |
574/// | [`SolverPlugin`] | Manages and solves contacts, [joints](dynamics::solver::joints), and other constraints. |
575/// | [`CcdPlugin`] | Performs sweep-based [Continuous Collision Detection](dynamics::ccd) for bodies with the [`SweptCcd`] component. |
576/// | [`SleepingPlugin`] | Manages sleeping and waking for bodies, automatically deactivating them to save computational resources. |
577/// | [`SpatialQueryPlugin`] | Handles spatial queries like [raycasting](spatial_query#raycasting) and [shapecasting](spatial_query#shapecasting). |
578/// | [`PhysicsInterpolationPlugin`] | [`Transform`] interpolation and extrapolation for rigid bodies. |
579/// | [`SyncPlugin`] | Keeps [`Position`] and [`Rotation`] in sync with `Transform`. |
580///
581/// Optional additional plugins include:
582///
583/// | Plugin | Description |
584/// | --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
585/// | [`PhysicsPickingPlugin`] | Enables a physics picking backend for [`bevy_picking`](bevy::picking) (only with `bevy_picking` feature enabled). |
586/// | [`PhysicsDebugPlugin`] | Renders physics objects and events like [AABBs](ColliderAabb) and contacts for debugging purposes (only with `debug-plugin` feature enabled). |
587/// | [`PhysicsDiagnosticsPlugin`] | Writes [physics diagnostics](diagnostics) to the [`DiagnosticsStore`] (only with `bevy_diagnostic` feature enabled). |
588/// | [`PhysicsDiagnosticsUiPlugin`] | Displays [physics diagnostics](diagnostics) with a debug UI overlay (only with `diagnostic_ui` feature enabled). |
589///
590/// [`DiagnosticsStore`]: bevy::diagnostic::DiagnosticsStore
591///
592/// Refer to the documentation of the plugins for more information about their responsibilities and implementations.
593///
594/// # World Scale
595///
596/// The [`PhysicsLengthUnit`] resource is a units-per-meter scaling factor
597/// that adjusts the engine's internal properties to the scale of the world.
598/// It is recommended to configure the length unit to match the approximate length
599/// of the average dynamic object in the world to get the best simulation results.
600///
601/// For example, a 2D game might use pixels as units and have an average object size
602/// of around 100 pixels. By setting the length unit to `100.0`, the physics engine
603/// will interpret 100 pixels as 1 meter for internal thresholds, improving stability.
604///
605/// The length unit can be set by inserting the resource like normal,
606/// but it can also be specified through the [`PhysicsPlugins`] plugin group.
607///
608/// ```no_run
609/// # #[cfg(feature = "2d")]
610/// use avian2d::prelude::*;
611/// use bevy::prelude::*;
612///
613/// # #[cfg(feature = "2d")]
614/// fn main() {
615/// App::new()
616/// .add_plugins((
617/// DefaultPlugins,
618/// // A 2D game with 100 pixels per meter
619/// PhysicsPlugins::default().with_length_unit(100.0),
620/// ))
621/// .run();
622/// }
623/// # #[cfg(not(feature = "2d"))]
624/// # fn main() {} // Doc test needs main
625/// ```
626///
627/// # Custom Schedule
628///
629/// You can run the [`PhysicsSchedule`] in any schedule you want by specifying the schedule when adding the plugin group:
630///
631/// ```no_run
632#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
633#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
634/// use bevy::prelude::*;
635///
636/// fn main() {
637/// App::new()
638/// // Run physics at a variable timestep in `PostUpdate`.
639/// .add_plugins((DefaultPlugins, PhysicsPlugins::new(PostUpdate)))
640/// .run();
641/// }
642/// ```
643///
644/// # Custom Plugins
645///
646/// First, create a new plugin. If you want to run your systems in the engine's schedules, get either the [`PhysicsSchedule`]
647/// or the [`SubstepSchedule`]. Then you can add your systems to that schedule and control system ordering with system sets like
648/// [`PhysicsStepSet`], [`SolverSet`], or [`SubstepSolverSet`](dynamics::solver::schedule::SubstepSolverSet).
649///
650/// Here we will create a custom broad phase plugin that will replace the default [`BroadPhasePlugin`]:
651///
652/// ```
653#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
654#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
655/// use bevy::prelude::*;
656///
657/// pub struct CustomBroadPhasePlugin;
658///
659/// impl Plugin for CustomBroadPhasePlugin {
660/// fn build(&self, app: &mut App) {
661/// // Make sure the PhysicsSchedule is available
662/// let physics_schedule = app
663/// .get_schedule_mut(PhysicsSchedule)
664/// .expect("add PhysicsSchedule first");
665///
666/// // Add the system into the broad phase system set
667/// physics_schedule.add_systems(collect_collision_pairs.in_set(PhysicsStepSet::BroadPhase));
668/// }
669/// }
670///
671/// fn collect_collision_pairs() {
672/// // Implementation goes here
673/// }
674/// ```
675///
676/// Next, when creating your app, simply disable the default [`BroadPhasePlugin`] and add your custom plugin:
677///
678/// ```no_run
679#[cfg_attr(feature = "2d", doc = "use avian2d::prelude::*;")]
680#[cfg_attr(feature = "3d", doc = "use avian3d::prelude::*;")]
681/// use bevy::prelude::*;
682///
683/// # struct CustomBroadPhasePlugin;
684/// # impl Plugin for CustomBroadPhasePlugin {
685/// # fn build(&self, app: &mut App) {}
686/// # }
687/// #
688/// fn main() {
689/// let mut app = App::new();
690///
691/// app.add_plugins(DefaultPlugins);
692///
693/// // Add PhysicsPlugins and replace default broad phase with our custom broad phase
694/// app.add_plugins(
695/// PhysicsPlugins::default()
696/// .build()
697/// .disable::<BroadPhasePlugin>()
698/// .add(CustomBroadPhasePlugin),
699/// );
700///
701/// app.run();
702/// }
703/// ```
704///
705/// You can find a full working example
706/// [here](https://github.com/Jondolf/avian/blob/main/crates/avian3d/examples/custom_broad_phase.rs).
707pub struct PhysicsPlugins {
708 schedule: Interned<dyn ScheduleLabel>,
709 length_unit: Scalar,
710}
711
712impl PhysicsPlugins {
713 /// Creates a [`PhysicsPlugins`] plugin group using the given schedule for running the [`PhysicsSchedule`].
714 ///
715 /// The default schedule is `FixedPostUpdate`.
716 pub fn new(schedule: impl ScheduleLabel) -> Self {
717 Self {
718 schedule: schedule.intern(),
719 length_unit: 1.0,
720 }
721 }
722
723 /// Adds the given [`CollisionHooks`] for user-defined contact filtering and modification.
724 ///
725 /// Returns a [`PhysicsPluginsWithHooks`] plugin group, which wraps the original [`PhysicsPlugins`],
726 /// and applies the provided hooks. Only one set of collision hooks can be defined per application.
727 pub fn with_collision_hooks<H: CollisionHooks + 'static>(self) -> PhysicsPluginsWithHooks<H>
728 where
729 for<'w, 's> SystemParamItem<'w, 's, H>: CollisionHooks,
730 {
731 PhysicsPluginsWithHooks::<H> {
732 plugins: self,
733 _phantom: core::marker::PhantomData,
734 }
735 }
736
737 /// Sets the value used for the [`PhysicsLengthUnit`], a units-per-meter scaling factor
738 /// that adjusts the engine's internal properties to the scale of the world.
739 ///
740 /// For example, a 2D game might use pixels as units and have an average object size
741 /// of around 100 pixels. By setting the length unit to `100.0`, the physics engine
742 /// will interpret 100 pixels as 1 meter for internal thresholds, improving stability.
743 ///
744 /// Note that this is *not* used to scale forces or any other user-facing inputs or outputs.
745 /// Instead, the value is only used to scale some internal length-based tolerances, such as
746 /// [`SleepingThreshold::linear`] and [`NarrowPhaseConfig::default_speculative_margin`],
747 /// as well as the scale used for [debug rendering](PhysicsDebugPlugin).
748 ///
749 /// Choosing the appropriate length unit can help improve stability and robustness.
750 ///
751 /// # Example
752 ///
753 /// ```no_run
754 /// # #[cfg(feature = "2d")]
755 /// use avian2d::prelude::*;
756 /// use bevy::prelude::*;
757 ///
758 /// # #[cfg(feature = "2d")]
759 /// fn main() {
760 /// App::new()
761 /// .add_plugins((
762 /// DefaultPlugins,
763 /// // A 2D game with 100 pixels per meter
764 /// PhysicsPlugins::default().with_length_unit(100.0),
765 /// ))
766 /// .run();
767 /// }
768 /// # #[cfg(not(feature = "2d"))]
769 /// # fn main() {} // Doc test needs main
770 /// ```
771 pub fn with_length_unit(mut self, unit: Scalar) -> Self {
772 self.length_unit = unit;
773 self
774 }
775}
776
777impl Default for PhysicsPlugins {
778 fn default() -> Self {
779 Self::new(FixedPostUpdate)
780 }
781}
782
783impl PluginGroup for PhysicsPlugins {
784 fn build(self) -> PluginGroupBuilder {
785 let builder = PluginGroupBuilder::start::<Self>()
786 .add(PhysicsSchedulePlugin::new(self.schedule))
787 .add(PhysicsTypeRegistrationPlugin)
788 .add(PreparePlugin::new(self.schedule))
789 .add(MassPropertyPlugin::new(self.schedule))
790 .add(ColliderHierarchyPlugin)
791 .add(ColliderTransformPlugin::new(self.schedule));
792
793 #[cfg(all(
794 feature = "default-collider",
795 any(feature = "parry-f32", feature = "parry-f64")
796 ))]
797 let builder = builder
798 .add(ColliderBackendPlugin::<Collider>::new(self.schedule))
799 .add(NarrowPhasePlugin::<Collider>::default());
800
801 builder
802 .add(BroadPhasePlugin::<()>::default())
803 .add(IntegratorPlugin::default())
804 .add(SolverPlugin::new_with_length_unit(self.length_unit))
805 .add(SolverSchedulePlugin)
806 .add(CcdPlugin)
807 .add(SleepingPlugin)
808 .add(SpatialQueryPlugin)
809 .add(SyncPlugin::new(self.schedule))
810 .add(PhysicsInterpolationPlugin::default())
811 }
812}
813
814// This type is separate from `PhysicsPlugins` to avoid requiring users to use generics
815// like `PhysicsPlugins::<()>::default()` unless they actually want to use collision hooks.
816/// A [`PhysicsPlugins`] plugin group with [`CollisionHooks`] specified.
817pub struct PhysicsPluginsWithHooks<H: CollisionHooks> {
818 plugins: PhysicsPlugins,
819 _phantom: core::marker::PhantomData<H>,
820}
821
822impl<H: CollisionHooks> PhysicsPluginsWithHooks<H> {
823 /// Creates a new [`PhysicsPluginsWithHooks`] plugin group using the given [`CollisionHooks`]
824 /// and schedule for running the [`PhysicsSchedule`].
825 ///
826 /// The default schedule is [`FixedPostUpdate`].
827 pub fn new(schedule: impl ScheduleLabel) -> Self {
828 Self {
829 plugins: PhysicsPlugins::new(schedule),
830 _phantom: core::marker::PhantomData,
831 }
832 }
833
834 /// Sets the value used for the [`PhysicsLengthUnit`], a units-per-meter scaling factor
835 /// that adjusts the engine's internal properties to the scale of the world.
836 ///
837 /// See [`PhysicsPlugins::with_length_unit`] for more information.
838 pub fn with_length_unit(mut self, unit: Scalar) -> Self {
839 self.plugins.length_unit = unit;
840 self
841 }
842}
843
844impl<H: CollisionHooks> Default for PhysicsPluginsWithHooks<H> {
845 fn default() -> Self {
846 Self {
847 plugins: PhysicsPlugins::default(),
848 _phantom: core::marker::PhantomData,
849 }
850 }
851}
852
853impl<H: CollisionHooks + 'static> PluginGroup for PhysicsPluginsWithHooks<H>
854where
855 for<'w, 's> SystemParamItem<'w, 's, H>: CollisionHooks,
856{
857 fn build(self) -> PluginGroupBuilder {
858 // Replace the default collision hooks with the user-defined ones.
859 let builder = self
860 .plugins
861 .build()
862 .disable::<BroadPhasePlugin>()
863 .add(BroadPhasePlugin::<H>::default());
864
865 #[cfg(all(
866 feature = "default-collider",
867 any(feature = "parry-f32", feature = "parry-f64")
868 ))]
869 let builder = builder
870 .disable::<NarrowPhasePlugin<Collider>>()
871 .add(NarrowPhasePlugin::<Collider, H>::default());
872
873 builder
874 }
875}