@@ -247,6 +247,10 @@ where
247
247
. chain ( ) ,
248
248
) ;
249
249
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
+
250
254
// Add each set as necessary
251
255
if self . default_system_setup {
252
256
app. configure_sets (
@@ -498,4 +502,86 @@ mod test {
498
502
) ) ;
499
503
}
500
504
}
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
+ }
501
587
}
0 commit comments