Skip to content

Commit

Permalink
Speed up ColliderTransform propagation and extract collider hierarc…
Browse files Browse the repository at this point in the history
…hy logic into `ColliderHierarchyPlugin` (#377)

# Objective

**Note:** This is for the `bevy-0.14` branch, because it uses new observer functionality (although it's not strictly necessary). It will be merged to `main` for the upcoming release.

Fixes #356.

To handle transforms in collider hierarchies properly, the engine must currently propagate a `ColliderTransform` component down the hierarchy several times per frame. This is made even worse by the fact that this propagation is done at every *substep*, not just once or twice per frame.

This wouldn't be too bad if it only affected physics entities, but the current system traverses through *all* entities that have a `Transform`. As reported in #356, this leads to absolutely awful performance for scenes with a large number of non-physics entities. This means that the engine scales very poorly with entity count, which is unacceptable.

## Solution

### Speed up propagation with `ColliderAncestor`

When colliders are added as children, automatically mark all ancestors with the `ColliderAncestor` component. Similarly, clean up the markers when a collider is removed.

`ColliderTransform` is *only* propagated down trees with `ColliderAncestor` entities. This way, we can essentially skip all unnecessary propagation.

In a test scene with one root entity, 100,000 child entities, and 12 substeps, I was previously getting **~22 fps** even though the entities only had a `SpatialBundle` and no physics components. With the changes in this PR, I now get **~200 fps**. Adding colliders to individual entities doesn't impact performance in any meaningful way, as the propagation is only done for those entities.

Note that this propagation will be even less of an issue in the upcoming Avian release, because there it doesn't even need to be run in the substepping loop.

The `ColliderAncestor` logic has a pretty comprehensive unit test for adding and removing colliders in a hierarchy, but I haven't verified yet if simply changing the `Parent` without moving the `Collider` works as expected. Adding more tests and potentially fixing these more niche cases can be done in a follow-up.

### Add `ColliderHierarchyPlugin`

The `ColliderBackendPlugin` was getting *big*, so I decided to extract the logic related to hierarchies and `ColliderTransform` into a new `ColliderHierarchyPlugin`.

Ideally, you could use the plugins fully independently and for example completely abandon hierarchies if you wanted to, but currently, they are still lightly coupled. Eliminating this coupling is a task for a follow-up.

---

## Migration Guide

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.
  • Loading branch information
Jondolf authored Jun 21, 2024
1 parent d713567 commit 1570143
Show file tree
Hide file tree
Showing 8 changed files with 1,089 additions and 836 deletions.
6 changes: 4 additions & 2 deletions crates/bevy_xpbd_2d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,13 @@ required-features = ["2d"]

[dependencies]
bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" }
bevy = { version = "0.14.0-rc" }
bevy = { version = "0.14.0-rc", default-features = false }
bevy_math = { version = "0.14.0-rc" }
parry2d = { version = "0.15", optional = true }
parry2d-f64 = { version = "0.15", optional = true }
nalgebra = { version = "0.32.6", features = ["convert-glam027"], optional = true }
nalgebra = { version = "0.32.6", features = [
"convert-glam027",
], optional = true }
serde = { version = "1", features = ["derive"], optional = true }
derive_more = "0.99"
indexmap = "2.0.0"
Expand Down
6 changes: 4 additions & 2 deletions crates/bevy_xpbd_3d/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,13 @@ required-features = ["3d"]

[dependencies]
bevy_xpbd_derive = { path = "../bevy_xpbd_derive", version = "0.1" }
bevy = { version = "0.14.0-rc" }
bevy = { version = "0.14.0-rc", default-features = false }
bevy_math = { version = "0.14.0-rc" }
parry3d = { version = "0.15", optional = true }
parry3d-f64 = { version = "0.15", optional = true }
nalgebra = { version = "0.32.6", features = ["convert-glam027"], optional = true }
nalgebra = { version = "0.32.6", features = [
"convert-glam027",
], optional = true }
serde = { version = "1", features = ["derive"], optional = true }
derive_more = "0.99"
indexmap = "2.0.0"
Expand Down
Loading

0 comments on commit 1570143

Please sign in to comment.