@@ -25,7 +25,7 @@ pub mod prelude {
25
25
}
26
26
27
27
use bevy_app:: { prelude:: * , RunFixedMainLoop } ;
28
- use bevy_ecs:: event:: { event_queue_update_system , EventUpdateSignal } ;
28
+ use bevy_ecs:: event:: { signal_event_update_system , EventUpdateSignal , EventUpdates } ;
29
29
use bevy_ecs:: prelude:: * ;
30
30
use bevy_utils:: { tracing:: warn, Duration , Instant } ;
31
31
pub use crossbeam_channel:: TrySendError ;
@@ -61,7 +61,11 @@ impl Plugin for TimePlugin {
61
61
62
62
// ensure the events are not dropped until `FixedMain` systems can observe them
63
63
app. init_resource :: < EventUpdateSignal > ( )
64
- . add_systems ( FixedPostUpdate , event_queue_update_system) ;
64
+ . add_systems ( FixedPostUpdate , signal_event_update_system)
65
+ . add_systems (
66
+ First ,
67
+ bevy_ecs:: event:: reset_event_update_signal_system. after ( EventUpdates ) ,
68
+ ) ;
65
69
66
70
#[ cfg( feature = "bevy_ci_testing" ) ]
67
71
if let Some ( ci_testing_config) = app
@@ -142,3 +146,66 @@ fn time_system(
142
146
TimeUpdateStrategy :: ManualDuration ( duration) => time. update_with_duration ( * duration) ,
143
147
}
144
148
}
149
+
150
+ #[ cfg( test) ]
151
+ mod tests {
152
+ use crate :: { Fixed , Time , TimePlugin , TimeUpdateStrategy } ;
153
+ use bevy_app:: { App , Startup , Update } ;
154
+ use bevy_ecs:: event:: { Event , EventReader , EventWriter } ;
155
+ use std:: error:: Error ;
156
+ use std:: time:: Duration ;
157
+
158
+ #[ derive( Event ) ]
159
+ struct TestEvent < T : Default > {
160
+ sender : std:: sync:: mpsc:: Sender < T > ,
161
+ }
162
+
163
+ impl < T : Default > Drop for TestEvent < T > {
164
+ fn drop ( & mut self ) {
165
+ self . sender
166
+ . send ( T :: default ( ) )
167
+ . expect ( "Failed to send drop signal" ) ;
168
+ }
169
+ }
170
+
171
+ #[ test]
172
+ fn events_get_dropped_regression_test_11528 ( ) -> Result < ( ) , impl Error > {
173
+ let ( tx1, rx1) = std:: sync:: mpsc:: channel ( ) ;
174
+ let ( tx2, rx2) = std:: sync:: mpsc:: channel ( ) ;
175
+ let mut app = App :: new ( ) ;
176
+ app. add_plugins ( TimePlugin )
177
+ . add_event :: < TestEvent < i32 > > ( )
178
+ . add_event :: < TestEvent < ( ) > > ( )
179
+ . add_systems ( Startup , move |mut ev2 : EventWriter < TestEvent < ( ) > > | {
180
+ ev2. send ( TestEvent {
181
+ sender : tx2. clone ( ) ,
182
+ } ) ;
183
+ } )
184
+ . add_systems ( Update , move |mut ev1 : EventWriter < TestEvent < i32 > > | {
185
+ // Keep adding events so this event type is processed every update
186
+ ev1. send ( TestEvent {
187
+ sender : tx1. clone ( ) ,
188
+ } ) ;
189
+ } )
190
+ . add_systems (
191
+ Update ,
192
+ |mut ev1 : EventReader < TestEvent < i32 > > , mut ev2 : EventReader < TestEvent < ( ) > > | {
193
+ // Read events so they can be dropped
194
+ for _ in ev1. read ( ) { }
195
+ for _ in ev2. read ( ) { }
196
+ } ,
197
+ )
198
+ . insert_resource ( TimeUpdateStrategy :: ManualDuration (
199
+ Time :: < Fixed > :: default ( ) . timestep ( ) ,
200
+ ) ) ;
201
+
202
+ for _ in 0 ..10 {
203
+ app. update ( ) ;
204
+ }
205
+
206
+ // Check event type 1 as been dropped at least once
207
+ let _drop_signal = rx1. recv_timeout ( Duration :: from_millis ( 1000 ) ) ;
208
+ // Check event type 2 has been dropped
209
+ rx2. recv_timeout ( Duration :: from_millis ( 1000 ) )
210
+ }
211
+ }
0 commit comments