Speed up ColliderTransform
propagation and extract collider hierarchy logic into ColliderHierarchyPlugin
#377
+1,089
−836
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 tomain
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 withColliderAncestor
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 theParent
without moving theCollider
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 andColliderTransform
into a newColliderHierarchyPlugin
.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 newColliderHierarchyPlugin
, which by default is included in thePhysicsPlugins
plugin group.If you are adding plugins manually, make sure you have both if you want that functionality.