diff --git a/crates/bevy_ecs/src/system/system_param.rs b/crates/bevy_ecs/src/system/system_param.rs index 909e434c19242..6e6c4deadff3f 100644 --- a/crates/bevy_ecs/src/system/system_param.rs +++ b/crates/bevy_ecs/src/system/system_param.rs @@ -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. @@ -986,21 +988,17 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> { /// ``` /// # use bevy_ecs::prelude::*; /// # let world = &mut World::default(); -/// fn write_to_local(mut local: Local) { -/// *local = 42; -/// } -/// fn read_from_local(local: Local) -> usize { -/// *local +/// fn counter(mut count: Local) -> 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. @@ -1008,7 +1006,7 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> { /// ``` /// # use bevy_ecs::prelude::*; /// # let world = &mut World::default(); -/// fn counter_from_10(mut count: Local>) -> usize { +/// fn counter_from_10(mut count: Local>) -> u32 { /// let count = count.get_or_insert(10); /// *count += 1; /// *count @@ -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, mut double_count: Local) -> (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) { +/// *local = 42; +/// } +/// fn read_from_local(local: Local) -> 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>) { +/// // 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: ///