Skip to content

Commit 0bac137

Browse files
authored
Improve Local SystemParam text, examples (#21718)
# Objective Explain `Local<T>` better to newbies. ## Solution Add more examples of how to use `Local<T>` and document how `T` is initialized for this type. I tried to order the examples from basic information to more niche information. I have no clue if the configuration example is useful or even what it's trying to convey. The blame log shows that there was some configuration thing that was removed. Furthermore, I added a doc comment to the SystemParam impl giving a very short description of what it provides as a system parameter. I think all non-tuple impls should provide such a blurb so that looking at the implementations for the trait itself provides useful information besides just the name. If that is wanted, an issue should be opened for it. If it is not, either I or the reviewer who commits this can remove the line. ## Testing I ran the doctests. I also built the docs and checked that the links work.
1 parent 8919ad1 commit 0bac137

File tree

1 file changed

+65
-15
lines changed

1 file changed

+65
-15
lines changed

crates/bevy_ecs/src/system/system_param.rs

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -972,7 +972,9 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
972972
}
973973
}
974974

975-
/// A system local [`SystemParam`].
975+
/// A [`SystemParam`] that provides a system-private value of `T` that persists across system calls.
976+
///
977+
/// The initial value is created by calling `T`'s [`FromWorld::from_world`] (or [`Default::default`] if `T: Default`).
976978
///
977979
/// A local may only be accessed by the system itself and is therefore not visible to other systems.
978980
/// If two or more systems specify the same local type each will have their own unique local.
@@ -986,29 +988,25 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
986988
/// ```
987989
/// # use bevy_ecs::prelude::*;
988990
/// # 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
991+
/// fn counter(mut count: Local<u32>) -> u32 {
992+
/// *count += 1;
993+
/// *count
994994
/// }
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);
995+
/// let mut counter_system = IntoSystem::into_system(counter);
996+
/// counter_system.initialize(world);
999997
///
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);
998+
/// // Counter is initialized to u32's default value of 0, and increases to 1 on first run.
999+
/// assert_eq!(counter_system.run((), world).unwrap(), 1);
1000+
/// // Counter gets the same value and increases to 2 on its second call.
1001+
/// assert_eq!(counter_system.run((), world).unwrap(), 2);
10041002
/// ```
10051003
///
10061004
/// A simple way to set a different default value for a local is by wrapping the value with an Option.
10071005
///
10081006
/// ```
10091007
/// # use bevy_ecs::prelude::*;
10101008
/// # let world = &mut World::default();
1011-
/// fn counter_from_10(mut count: Local<Option<usize>>) -> usize {
1009+
/// fn counter_from_10(mut count: Local<Option<u32>>) -> u32 {
10121010
/// let count = count.get_or_insert(10);
10131011
/// *count += 1;
10141012
/// *count
@@ -1022,6 +1020,58 @@ unsafe impl<'w> SystemParam for DeferredWorld<'w> {
10221020
/// assert_eq!(counter_system.run((), world).unwrap(), 12);
10231021
/// ```
10241022
///
1023+
/// A system can have multiple `Local` values with the same type, each with distinct values.
1024+
///
1025+
/// ```
1026+
/// # use bevy_ecs::prelude::*;
1027+
/// # let world = &mut World::default();
1028+
/// fn double_counter(mut count: Local<u32>, mut double_count: Local<u32>) -> (u32, u32) {
1029+
/// *count += 1;
1030+
/// *double_count += 2;
1031+
/// (*count, *double_count)
1032+
/// }
1033+
/// let mut counter_system = IntoSystem::into_system(double_counter);
1034+
/// counter_system.initialize(world);
1035+
///
1036+
/// assert_eq!(counter_system.run((), world).unwrap(), (1, 2));
1037+
/// assert_eq!(counter_system.run((), world).unwrap(), (2, 4));
1038+
/// ```
1039+
///
1040+
/// This example shows that two systems using the same type for their own `Local` get distinct locals.
1041+
///
1042+
/// ```
1043+
/// # use bevy_ecs::prelude::*;
1044+
/// # let world = &mut World::default();
1045+
/// fn write_to_local(mut local: Local<usize>) {
1046+
/// *local = 42;
1047+
/// }
1048+
/// fn read_from_local(local: Local<usize>) -> usize {
1049+
/// *local
1050+
/// }
1051+
/// let mut write_system = IntoSystem::into_system(write_to_local);
1052+
/// let mut read_system = IntoSystem::into_system(read_from_local);
1053+
/// write_system.initialize(world);
1054+
/// read_system.initialize(world);
1055+
///
1056+
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1057+
/// write_system.run((), world);
1058+
/// // The read local is still 0 due to the locals not being shared.
1059+
/// assert_eq!(read_system.run((), world).unwrap(), 0);
1060+
/// ```
1061+
///
1062+
/// You can use a `Local` to avoid reallocating memory every system call.
1063+
///
1064+
/// ```
1065+
/// # use bevy_ecs::prelude::*;
1066+
/// fn some_system(mut vec: Local<Vec<u32>>) {
1067+
/// // Do your regular system logic, using the vec, as normal.
1068+
///
1069+
/// // At end of function, clear the vec's contents so its empty for next system call.
1070+
/// // If it's possible the capacity could get too large, you may want to check and resize that as well.
1071+
/// vec.clear();
1072+
/// }
1073+
/// ```
1074+
///
10251075
/// N.B. A [`Local`]s value cannot be read or written to outside of the containing system.
10261076
/// To add configuration to a system, convert a capturing closure into the system instead:
10271077
///

0 commit comments

Comments
 (0)