nphysics
nphysics copied to clipboard
Panic "Invalid parent body part handle" when creating and deleting a body in the same frame
I ran across a panic: thread 'main' panicked at 'Invalid parent body part handle.', src/libcore/option.rs:1188:5
that happens if a body is created/destroyed in the same frame. It looks like the source of this is that handle_insertions runs after the body is removed.
fn handle_insertions<Bodies, Colliders>(&mut self, bodies: &mut Bodies, colliders: &mut Colliders)
where Bodies: BodySet<N, Handle = Handle>,
Colliders: ColliderSet<N, Handle, Handle = CollHandle> {
while let Some(handle) = colliders.pop_insertion_event() {
if let Some(collider) = colliders.get_mut(handle) {
self.register_collider(handle, collider);
match collider.anchor() {
ColliderAnchor::OnBodyPart { body_part, position_wrt_body_part } => {
let body = bodies.get_mut(body_part.0).expect("Invalid parent body part handle.");
It looks like normally this bit of code at the top of MechanicalWorld::maintain would have used GeometricalWorld::body_colliders to find and remove the colliders ahead of time, causing GeometricalWorld::handle_insertions to do nothing.
// NOTE: the order of handling events matters.
// In particular, handling body removal events must be done first because it
// can itself cause constraints or colliders to be automatically removed too.
let mut at_least_one_body_removed = false; // If at least one body is removed we need to find the constraints to remove too.
while let Some(handle) = bodies.pop_removal_event() {
// Remove every colliders attached to this body.
if let Some(colls_to_remove) = gworld.body_colliders(handle) {
for collider in colls_to_remove {
let _ = colliders.remove(*collider);
}
}
at_least_one_body_removed = true;
}
However, GeometricalWorld::body_colliders doesn't get populated until handle_insertions runs, so the colliders are not removed.
@Ralith and I discussed a bit on discord, three general approaches to addressing this came up:
- Find and remove the queued handle_insertions if the body is removed
- Make the handle_insertions code detect the situation and do nothing
- Process insertions/removals in the order they actually occur instead of batching them together
While I think approach 1 or 2 might yield a quick fix, I think @ralith and I both feel that the third approach might be less error prone