Skip to content

Commit 821cde9

Browse files
authored
Fix sync_removals with low physics fixed rate (#600)
* fix sync_removals with low physics fixed rate * simplify test_sync_removal
1 parent cda43aa commit 821cde9

File tree

1 file changed

+86
-0
lines changed

1 file changed

+86
-0
lines changed

Diff for: src/plugin/plugin.rs

+86
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,10 @@ where
247247
.chain(),
248248
);
249249

250+
// These *must* be in the main schedule currently so that they do not miss events.
251+
// See test `test_sync_removal` for an example of this.
252+
app.add_systems(PostUpdate, (systems::sync_removals,));
253+
250254
// Add each set as necessary
251255
if self.default_system_setup {
252256
app.configure_sets(
@@ -498,4 +502,86 @@ mod test {
498502
));
499503
}
500504
}
505+
506+
#[test]
507+
pub fn test_sync_removal() {
508+
return main();
509+
510+
use bevy::prelude::*;
511+
512+
fn run_test(app: &mut App) {
513+
app.insert_resource(TimeUpdateStrategy::ManualDuration(
514+
std::time::Duration::from_secs_f32(1f32 / 60f32),
515+
));
516+
app.insert_resource(Time::<Fixed>::from_hz(20.0));
517+
518+
app.add_systems(Startup, setup_physics);
519+
app.add_systems(Update, remove_rapier_entity);
520+
app.add_systems(FixedUpdate, || println!("Fixed Update"));
521+
app.add_systems(Update, || println!("Update"));
522+
// startup
523+
app.update();
524+
// normal updates starting
525+
// render only
526+
app.update();
527+
app.update();
528+
// render + physics
529+
app.update();
530+
531+
let context = app
532+
.world_mut()
533+
.query::<&RapierContext>()
534+
.get_single(&app.world())
535+
.unwrap();
536+
assert_eq!(context.entity2body.len(), 1);
537+
538+
// render only + remove entities
539+
app.update();
540+
// Fixed Update hasn´t run yet, so it's a risk of not having caught the bevy removed event, which will be cleaned next frame.
541+
542+
let context = app
543+
.world_mut()
544+
.query::<&RapierContext>()
545+
.get_single(&app.world())
546+
.unwrap();
547+
548+
println!("{:?}", &context.entity2body);
549+
assert_eq!(context.entity2body.len(), 0);
550+
}
551+
552+
fn main() {
553+
let mut app = App::new();
554+
app.add_plugins((
555+
HeadlessRenderPlugin,
556+
TransformPlugin,
557+
TimePlugin,
558+
RapierPhysicsPlugin::<NoUserData>::default().in_fixed_schedule(),
559+
));
560+
run_test(&mut app);
561+
}
562+
563+
pub fn setup_physics(mut commands: Commands) {
564+
commands.spawn((
565+
TransformBundle::from(Transform::from_xyz(0.0, 13.0, 0.0)),
566+
RigidBody::Dynamic,
567+
cuboid(0.5, 0.5, 0.5),
568+
TestMarker,
569+
));
570+
println!("spawned rapier entity");
571+
}
572+
pub fn remove_rapier_entity(
573+
mut commands: Commands,
574+
to_remove: Query<Entity, With<TestMarker>>,
575+
mut counter: Local<i32>,
576+
) {
577+
*counter += 1;
578+
if *counter != 5 {
579+
return;
580+
}
581+
println!("removing rapier entity");
582+
for e in &to_remove {
583+
commands.entity(e).despawn();
584+
}
585+
}
586+
}
501587
}

0 commit comments

Comments
 (0)