@@ -239,6 +239,114 @@ fn assert_component_access_compatibility(
239
239
query_type, filter_type, system_name, accesses) ;
240
240
}
241
241
242
+ /// A collection of potentially conflicting [`SystemParam`]s allowed by disjoint access.
243
+ ///
244
+ /// Allows systems to safely access and interact with up to 8 mutually exclusive [`SystemParam`]s, such as
245
+ /// two queries that reference the same mutable data or an event reader and writer of the same type.
246
+ ///
247
+ /// Each individual [`SystemParam`] can be accessed by using the functions `p0()`, `p1()`, ..., `p7()`,
248
+ /// according to the order they are defined in the `ParamSet`. This ensures that there's either
249
+ /// only one mutable reference to a parameter at a time or any number of immutable references.
250
+ ///
251
+ /// # Examples
252
+ ///
253
+ /// The following system mutably accesses the same component two times,
254
+ /// which is not allowed due to rust's mutability rules.
255
+ ///
256
+ /// ```should_panic
257
+ /// # use bevy_ecs::prelude::*;
258
+ /// #
259
+ /// # #[derive(Component)]
260
+ /// # struct Health;
261
+ /// #
262
+ /// # #[derive(Component)]
263
+ /// # struct Enemy;
264
+ /// #
265
+ /// # #[derive(Component)]
266
+ /// # struct Ally;
267
+ /// #
268
+ /// // This will panic at runtime when the system gets initialized.
269
+ /// fn bad_system(
270
+ /// mut enemies: Query<&mut Health, With<Enemy>>,
271
+ /// mut allies: Query<&mut Health, With<Ally>>,
272
+ /// ) {
273
+ /// // ...
274
+ /// }
275
+ /// #
276
+ /// # let mut bad_system_system = bevy_ecs::system::IntoSystem::into_system(bad_system);
277
+ /// # let mut world = World::new();
278
+ /// # bad_system_system.initialize(&mut world);
279
+ /// # bad_system_system.run((), &mut world);
280
+ /// ```
281
+ ///
282
+ /// Conflicing `SystemParam`s like these can be placed in a `ParamSet`,
283
+ /// which leverages the borrow checker to ensure that only one of the contained parameters are accessed at a given time.
284
+ ///
285
+ /// ```
286
+ /// # use bevy_ecs::prelude::*;
287
+ /// #
288
+ /// # #[derive(Component)]
289
+ /// # struct Health;
290
+ /// #
291
+ /// # #[derive(Component)]
292
+ /// # struct Enemy;
293
+ /// #
294
+ /// # #[derive(Component)]
295
+ /// # struct Ally;
296
+ /// #
297
+ /// // Given the following system
298
+ /// fn fancy_system(
299
+ /// mut set: ParamSet<(
300
+ /// Query<&mut Health, With<Enemy>>,
301
+ /// Query<&mut Health, With<Ally>>,
302
+ /// )>
303
+ /// ) {
304
+ /// // This will access the first `SystemParam`.
305
+ /// for mut health in set.p0().iter_mut() {
306
+ /// // Do your fancy stuff here...
307
+ /// }
308
+ ///
309
+ /// // The second `SystemParam`.
310
+ /// // This would fail to compile if the previous parameter was still borrowed.
311
+ /// for mut health in set.p1().iter_mut() {
312
+ /// // Do even fancier stuff here...
313
+ /// }
314
+ /// }
315
+ /// # bevy_ecs::system::assert_is_system(fancy_system);
316
+ /// ```
317
+ ///
318
+ /// Of course, `ParamSet`s can be used with any kind of `SystemParam`, not just [queries](Query).
319
+ ///
320
+ /// ```
321
+ /// # use bevy_ecs::prelude::*;
322
+ /// #
323
+ /// # struct MyEvent;
324
+ /// # impl MyEvent {
325
+ /// # pub fn new() -> Self { Self }
326
+ /// # }
327
+ /// fn event_system(
328
+ /// mut set: ParamSet<(
329
+ /// // `EventReader`s and `EventWriter`s conflict with each other,
330
+ /// // since they both access the event queue resource for `MyEvent`.
331
+ /// EventReader<MyEvent>,
332
+ /// EventWriter<MyEvent>,
333
+ /// // `&World` reads the entire world, so a `ParamSet` is the only way
334
+ /// // that it can be used in the same system as any mutable accesses.
335
+ /// &World,
336
+ /// )>,
337
+ /// ) {
338
+ /// for event in set.p0().iter() {
339
+ /// // ...
340
+ /// # let _event = event;
341
+ /// }
342
+ /// set.p1().send(MyEvent::new());
343
+ ///
344
+ /// let entities = set.p2().entities();
345
+ /// // ...
346
+ /// # let _entities = entities;
347
+ /// }
348
+ /// # bevy_ecs::system::assert_is_system(event_system);
349
+ /// ```
242
350
pub struct ParamSet < ' w , ' s , T : SystemParam > {
243
351
param_states : & ' s mut T :: State ,
244
352
world : & ' w World ,
0 commit comments