Skip to content

Commit d4b95e7

Browse files
committed
Doc - Improve Local SystemParam text, examples
1 parent e3814a9 commit d4b95e7

File tree

1 file changed

+55
-14
lines changed

1 file changed

+55
-14
lines changed

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,10 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
974974

975975
/// A system local [`SystemParam`].
976976
///
977+
/// A system with a `Local<T>` parameter is given a private value of `T` that persists across system calls.
978+
///
979+
/// The initial value is created by calling `T`'s [`FromWorld::from_world`] (or [`Default::default`] if `T: Default`).
980+
///
977981
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
978982
/// If two or more systems specify the same local type each will have their own unique local.
979983
/// If multiple [`SystemParam`]s within the same system each specify the same local type
@@ -986,29 +990,25 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
986990
/// ```
987991
/// # use bevy_ecs::prelude::*;
988992
/// # let world = &mut World::default();
989-
/// fn write_to_local(mut local: Local<usize>) {
990-
/// *local = 42;
991-
/// }
992-
/// fn read_from_local(local: Local<usize>) -> usize {
993-
/// *local
993+
/// fn counter(mut count: Local<u32>) -> u32 {
994+
/// *count += 1;
995+
/// *count
994996
/// }
995-
/// let mut write_system = IntoSystem::into_system(write_to_local);
996-
/// let mut read_system = IntoSystem::into_system(read_from_local);
997-
/// write_system.initialize(world);
998-
/// read_system.initialize(world);
997+
/// let mut counter_system = IntoSystem::into_system(counter);
998+
/// counter_system.initialize(world);
999999
///
1000-
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1001-
/// write_system.run((), world);
1002-
/// // Note how the read local is still 0 due to the locals not being shared.
1003-
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1000+
/// // Counter is initialized to u32's default value of 0, and increases to 1 on first run.
1001+
/// assert_eq!(counter_system.run((), world).unwrap(), 1);
1002+
/// // Counter gets the same value and increases to 2 on its second call.
1003+
/// assert_eq!(counter_system.run((), world).unwrap(), 2);
10041004
/// ```
10051005
///
10061006
/// A simple way to set a different default value for a local is by wrapping the value with an Option.
10071007
///
10081008
/// ```
10091009
/// # use bevy_ecs::prelude::*;
10101010
/// # let world = &mut World::default();
1011-
/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {
1011+
/// fn counter_from_10(mut count: Local<Option<u32>>) -> u32 {
10121012
/// let count = count.get_or_insert(10);
10131013
/// *count += 1;
10141014
/// *count
@@ -1022,6 +1022,46 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
10221022
/// assert_eq!(counter_system.run((), world).unwrap(), 12);
10231023
/// ```
10241024
///
1025+
/// A system having multiple locals with the same type are distinct values.
1026+
///
1027+
/// ```
1028+
/// # use bevy_ecs::prelude::*;
1029+
/// # let world = &mut World::default();
1030+
/// fn double_counter(mut count: Local<u32>, mut double_count: Local<u32>) -> (u32, u32) {
1031+
/// *count += 1;
1032+
/// *double_count += 2;
1033+
/// (*count, *double_count)
1034+
/// }
1035+
/// let mut counter_system = IntoSystem::into_system(double_counter);
1036+
/// counter_system.initialize(world);
1037+
///
1038+
/// assert_eq!(counter_system.run((), world).unwrap(), (1, 2));
1039+
/// // Counter is only increased by 1 on subsequent runs.
1040+
/// assert_eq!(counter_system.run((), world).unwrap(), (2, 4));
1041+
/// ```
1042+
///
1043+
/// This example shows that two systems using the same type for their own local get different locals.
1044+
///
1045+
/// ```
1046+
/// # use bevy_ecs::prelude::*;
1047+
/// # let world = &mut World::default();
1048+
/// fn write_to_local(mut local: Local<usize>) {
1049+
/// *local = 42;
1050+
/// }
1051+
/// fn read_from_local(local: Local<usize>) -> usize {
1052+
/// *local
1053+
/// }
1054+
/// let mut write_system = IntoSystem::into_system(write_to_local);
1055+
/// let mut read_system = IntoSystem::into_system(read_from_local);
1056+
/// write_system.initialize(world);
1057+
/// read_system.initialize(world);
1058+
///
1059+
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1060+
/// write_system.run((), world);
1061+
/// // The read local is still 0 due to the locals not being shared.
1062+
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1063+
/// ```
1064+
///
10251065
/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
10261066
/// To add configuration to a system, convert a capturing closure into the system instead:
10271067
///
@@ -1085,6 +1125,7 @@ where
10851125
}
10861126

10871127
// SAFETY: only local state is accessed
1128+
/// System private persistent value
10881129
unsafe impl<'a, T: FromWorld + Send + 'static> SystemParam for Local<'a, T> {
10891130
type State = SyncCell<T>;
10901131
type Item<'w, 's> = Local<'s, T>;

0 commit comments

Comments
 (0)