`WorldPlugins` has disabled `MassPropertyPlugin` for as long as the world has
had colliders, with the reason written beside it: there are no dynamic bodies,
so no mass is ever read. The pass kept running anyway. `ColliderBackendPlugin`,
which we keep for `update_collider_scale`, registers
`update_collider_mass_properties` itself (`collision/collider/backend.rs:232`),
and that system's query filters `Without<Sensor>` and nothing about the body
type — so every collider that *changed* paid `Collider::mass_properties`, a
full parry volume integral over the trimesh, for a value with no reader.
Terrain streams its colliders as trimeshes by the tile, so the cost lands in a
world load. Measured on a cold Elwynn vista with `WOW_SYSTEM_TIMING=1`, before
and after, same viewpoint:
before run_fixed_main_schedule worst 183.0 ms 200.9 ms/s
after run_fixed_main_schedule worst 1.3 ms 25.9 ms/s
`update_collider_mass_properties` no longer appears in the report at all, and
its 181.3 ms worst run was the whole of that schedule's spike — the nesting is
what identified it.
A run condition rather than another `.disable()`, because the system cannot be
removed individually and shares a `.chain()` with `update_collider_scale`.
`MassPropertySystems` is `pub` but not in avian's prelude, hence the full path.
The invariant the whole physics trim rests on now has a wall of its own:
`tests/no_dynamic_bodies_wall.rs` fails if `RigidBody::Dynamic` appears in the
workspace. This bug was exactly an invariant that lived only in prose — the
`.disable()` comment stated it correctly while a system slipped through the gap
between two plugins — so the assert is the point. Verified by planting a
dynamic body and watching it fail, then reverting.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgstFWtn1RxEJ5kVrpgYwn