Skip to content

Commit a383159

Browse files
authored
Add system that asserts physics components are finite (#909)
# Objective A lot of people (me included) have had to track down NaNs or infinities that causes avian internals to crash, and they can be difficult to track down because they cause crashes a lot later than they are introduced. ## Solution Add a system when running with debug assertions that checks relevant components during `PhysicsSystems::First`. For bugs in Avian internals we can potentially also schedule this system in other places. ### Questions * I placed it in `PhysicsSchedulePlugin` because it feels more general purpose than the rest of `PhysicsDebugPlugin` and because it needs `self.schedule`, but I'm not sure if that's the best location for it? * We could make the system use `assert!` instead of `debug_assert!` and make it runnable outside of `debug_assertions`? ## Testing I modified one of the examples to introduce an infinity during Update and saw that it was caught.
1 parent 0c06418 commit a383159

File tree

1 file changed

+36
-0
lines changed

1 file changed

+36
-0
lines changed

src/schedule/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ impl Plugin for PhysicsSchedulePlugin {
117117
PhysicsSchedule,
118118
update_last_physics_tick.after(PhysicsStepSystems::Last),
119119
);
120+
121+
#[cfg(debug_assertions)]
122+
app.add_systems(
123+
schedule,
124+
assert_components_finite.in_set(PhysicsSystems::First),
125+
);
120126
}
121127
}
122128

@@ -283,3 +289,33 @@ fn update_last_physics_tick(
283289
) {
284290
last_physics_tick.0 = system_change_tick.this_run();
285291
}
292+
293+
/// Debug system that checks for NaNs and infinities in Avian components and
294+
/// reports the last location they were written to.
295+
#[cfg(debug_assertions)]
296+
fn assert_components_finite(
297+
pos_query: Query<(Entity, Ref<Position>)>,
298+
lin_vel_query: Query<(Entity, Ref<LinearVelocity>)>,
299+
ang_vel_query: Query<(Entity, Ref<AngularVelocity>)>,
300+
) {
301+
macro_rules! assert_finite {
302+
($ent:expr, $val:ident, $ty:ty) => {
303+
debug_assert!(
304+
$val.is_finite(),
305+
"NaN or infinity found in Avian component: type={} entity={} location='{}' (enable feature \"bevy/track_location\" if location is empty)",
306+
stringify!($ty),
307+
$ent,
308+
$val.changed_by()
309+
);
310+
};
311+
}
312+
for (entity, position) in pos_query {
313+
assert_finite!(entity, position, Position);
314+
}
315+
for (entity, velocity) in lin_vel_query {
316+
assert_finite!(entity, velocity, LinearVelocity);
317+
}
318+
for (entity, velocity) in ang_vel_query {
319+
assert_finite!(entity, velocity, AngularVelocity);
320+
}
321+
}

0 commit comments

Comments
 (0)