Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 65 additions & 15 deletions crates/bevy_ecs/src/system/system_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,9 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
}
}

/// A system local [`SystemParam`].
/// A [`SystemParam`] that provides a system-private value of `T` that persists across system calls.
///
/// The initial value is created by calling `T`'s [`FromWorld::from_world`] (or [`Default::default`] if `T: Default`).
///
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
/// If two or more systems specify the same local type each will have their own unique local.
Expand All @@ -986,29 +988,25 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
/// ```
/// # use bevy_ecs::prelude::*;
/// # let world = &mut World::default();
/// fn write_to_local(mut local: Local<usize>) {
/// *local = 42;
/// }
/// fn read_from_local(local: Local<usize>) -> usize {
/// *local
/// fn counter(mut count: Local<u32>) -> u32 {
/// *count += 1;
/// *count
/// }
/// let mut write_system = IntoSystem::into_system(write_to_local);
/// let mut read_system = IntoSystem::into_system(read_from_local);
/// write_system.initialize(world);
/// read_system.initialize(world);
/// let mut counter_system = IntoSystem::into_system(counter);
/// counter_system.initialize(world);
///
/// assert_eq!(read_system.run((), world).unwrap(), 0);
/// write_system.run((), world);
/// // Note how the read local is still 0 due to the locals not being shared.
/// assert_eq!(read_system.run((), world).unwrap(), 0);
/// // Counter is initialized to u32's default value of 0, and increases to 1 on first run.
/// assert_eq!(counter_system.run((), world).unwrap(), 1);
/// // Counter gets the same value and increases to 2 on its second call.
/// assert_eq!(counter_system.run((), world).unwrap(), 2);
/// ```
///
/// A simple way to set a different default value for a local is by wrapping the value with an Option.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let world = &mut World::default();
/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {
/// fn counter_from_10(mut count: Local<Option<u32>>) -> u32 {
/// let count = count.get_or_insert(10);
/// *count += 1;
/// *count
Expand All @@ -1022,6 +1020,58 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
/// assert_eq!(counter_system.run((), world).unwrap(), 12);
/// ```
///
/// A system can have multiple `Local` values with the same type, each with distinct values.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let world = &mut World::default();
/// fn double_counter(mut count: Local<u32>, mut double_count: Local<u32>) -> (u32, u32) {
/// *count += 1;
/// *double_count += 2;
/// (*count, *double_count)
/// }
/// let mut counter_system = IntoSystem::into_system(double_counter);
/// counter_system.initialize(world);
///
/// assert_eq!(counter_system.run((), world).unwrap(), (1, 2));
/// assert_eq!(counter_system.run((), world).unwrap(), (2, 4));
/// ```
///
/// This example shows that two systems using the same type for their own `Local` get distinct locals.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// # let world = &mut World::default();
/// fn write_to_local(mut local: Local<usize>) {
/// *local = 42;
/// }
/// fn read_from_local(local: Local<usize>) -> usize {
/// *local
/// }
/// let mut write_system = IntoSystem::into_system(write_to_local);
/// let mut read_system = IntoSystem::into_system(read_from_local);
/// write_system.initialize(world);
/// read_system.initialize(world);
///
/// assert_eq!(read_system.run((), world).unwrap(), 0);
/// write_system.run((), world);
/// // The read local is still 0 due to the locals not being shared.
/// assert_eq!(read_system.run((), world).unwrap(), 0);
/// ```
///
/// You can use a `Local` to avoid reallocating memory every system call.
///
/// ```
/// # use bevy_ecs::prelude::*;
/// fn some_system(mut vec: Local<Vec<u32>>) {
/// // Do your regular system logic, using the vec, as normal.
///
/// // At end of function, clear the vec's contents so its empty for next system call.
/// // If it's possible the capacity could get too large, you may want to check and resize that as well.
/// vec.clear();
/// }
/// ```
///
/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
/// To add configuration to a system, convert a capturing closure into the system instead:
///
Expand Down