Struct bevy::ecs::system::SystemState

source ·
pub struct SystemState<Param>
where Param: SystemParam + 'static,
{ /* private fields */ }
Expand description

Holds on to persistent state required to drive SystemParam for a System.

This is a powerful and convenient tool for working with exclusive world access, allowing you to fetch data from the World as if you were running a System. However, simply calling world::run_system(my_system) using a World::run_system can be significantly simpler and ensures that change detection and command flushing work as expected.

Borrow-checking is handled for you, allowing you to mutably access multiple compatible system parameters at once, and arbitrary system parameters (like EventWriter) can be conveniently fetched.

For an alternative approach to split mutable access to the world, see World::resource_scope.

§Warning

SystemState values created can be cached to improve performance, and must be cached and reused in order for system parameters that rely on local state to work correctly. These include:

Note that this is automatically handled for you when using a World::run_system.

§Example

Basic usage:

// Work directly on the `World`
let mut world = World::new();
world.init_resource::<Events<MyEvent>>();

// Construct a `SystemState` struct, passing in a tuple of `SystemParam`
// as if you were writing an ordinary system.
let mut system_state: SystemState<(
    EventWriter<MyEvent>,
    Option<ResMut<MyResource>>,
    Query<&MyComponent>,
)> = SystemState::new(&mut world);

// Use system_state.get_mut(&mut world) and unpack your system parameters into variables!
// system_state.get(&world) provides read-only versions of your system parameters instead.
let (event_writer, maybe_resource, query) = system_state.get_mut(&mut world);

// If you are using `Commands`, you can choose when you want to apply them to the world.
// You need to manually call `.apply(world)` on the `SystemState` to apply them.

Caching:

#[derive(Resource)]
struct CachedSystemState {
    event_state: SystemState<EventReader<'static, 'static, MyEvent>>,
}

// Create and store a system state once
let mut world = World::new();
world.init_resource::<Events<MyEvent>>();
let initial_state: SystemState<EventReader<MyEvent>> = SystemState::new(&mut world);

// The system state is cached in a resource
world.insert_resource(CachedSystemState {
    event_state: initial_state,
});

// Later, fetch the cached system state, saving on overhead
world.resource_scope(|world, mut cached_state: Mut<CachedSystemState>| {
    let mut event_reader = cached_state.event_state.get_mut(world);

    for events in event_reader.read() {
        println!("Hello World!");
    }
});

Implementations§

source§

impl<Param> SystemState<Param>
where Param: SystemParam,

source

pub fn new(world: &mut World) -> SystemState<Param>

Creates a new SystemState with default state.

§Note

For users of SystemState::get_manual or get_manual_mut:

new does not cache any of the world’s archetypes, so you must call SystemState::update_archetypes manually before calling get_manual{_mut}.

Examples found in repository?
examples/async_tasks/async_compute.rs (lines 77-80)
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
fn spawn_tasks(mut commands: Commands) {
    let thread_pool = AsyncComputeTaskPool::get();
    for x in 0..NUM_CUBES {
        for y in 0..NUM_CUBES {
            for z in 0..NUM_CUBES {
                // Spawn new task on the AsyncComputeTaskPool; the task will be
                // executed in the background, and the Task future returned by
                // spawn() can be used to poll for the result
                let entity = commands.spawn_empty().id();
                let task = thread_pool.spawn(async move {
                    let mut rng = rand::thread_rng();

                    let duration = Duration::from_secs_f32(rng.gen_range(0.05..0.2));

                    // Pretend this is a time-intensive function. :)
                    thread::sleep(duration);

                    // Such hard work, all done!
                    let transform = Transform::from_xyz(x as f32, y as f32, z as f32);
                    let mut command_queue = CommandQueue::default();

                    // we use a raw command queue to pass a FnOne(&mut World) back to be
                    // applied in a deferred manner.
                    command_queue.push(move |world: &mut World| {
                        let (box_mesh_handle, box_material_handle) = {
                            let mut system_state = SystemState::<(
                                Res<BoxMeshHandle>,
                                Res<BoxMaterialHandle>,
                            )>::new(world);
                            let (box_mesh_handle, box_material_handle) =
                                system_state.get_mut(world);

                            (box_mesh_handle.clone(), box_material_handle.clone())
                        };

                        world
                            .entity_mut(entity)
                            // Add our new PbrBundle of components to our tagged entity
                            .insert(PbrBundle {
                                mesh: box_mesh_handle,
                                material: box_material_handle,
                                transform,
                                ..default()
                            })
                            // Task is complete, so remove task component from entity
                            .remove::<ComputeTransform>();
                    });

                    command_queue
                });

                // Spawn new entity and add our new task as a component
                commands.entity(entity).insert(ComputeTransform(task));
            }
        }
    }
}
source

pub fn meta(&self) -> &SystemMeta

Gets the metadata for this instance.

source

pub fn get<'w, 's>( &'s mut self, world: &'w World ) -> <Param as SystemParam>::Item<'w, 's>
where Param: ReadOnlySystemParam,

Retrieve the SystemParam values. This can only be called when all parameters are read-only.

source

pub fn get_mut<'w, 's>( &'s mut self, world: &'w mut World ) -> <Param as SystemParam>::Item<'w, 's>

Retrieve the mutable SystemParam values.

Examples found in repository?
examples/async_tasks/async_compute.rs (line 82)
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
fn spawn_tasks(mut commands: Commands) {
    let thread_pool = AsyncComputeTaskPool::get();
    for x in 0..NUM_CUBES {
        for y in 0..NUM_CUBES {
            for z in 0..NUM_CUBES {
                // Spawn new task on the AsyncComputeTaskPool; the task will be
                // executed in the background, and the Task future returned by
                // spawn() can be used to poll for the result
                let entity = commands.spawn_empty().id();
                let task = thread_pool.spawn(async move {
                    let mut rng = rand::thread_rng();

                    let duration = Duration::from_secs_f32(rng.gen_range(0.05..0.2));

                    // Pretend this is a time-intensive function. :)
                    thread::sleep(duration);

                    // Such hard work, all done!
                    let transform = Transform::from_xyz(x as f32, y as f32, z as f32);
                    let mut command_queue = CommandQueue::default();

                    // we use a raw command queue to pass a FnOne(&mut World) back to be
                    // applied in a deferred manner.
                    command_queue.push(move |world: &mut World| {
                        let (box_mesh_handle, box_material_handle) = {
                            let mut system_state = SystemState::<(
                                Res<BoxMeshHandle>,
                                Res<BoxMaterialHandle>,
                            )>::new(world);
                            let (box_mesh_handle, box_material_handle) =
                                system_state.get_mut(world);

                            (box_mesh_handle.clone(), box_material_handle.clone())
                        };

                        world
                            .entity_mut(entity)
                            // Add our new PbrBundle of components to our tagged entity
                            .insert(PbrBundle {
                                mesh: box_mesh_handle,
                                material: box_material_handle,
                                transform,
                                ..default()
                            })
                            // Task is complete, so remove task component from entity
                            .remove::<ComputeTransform>();
                    });

                    command_queue
                });

                // Spawn new entity and add our new task as a component
                commands.entity(entity).insert(ComputeTransform(task));
            }
        }
    }
}
source

pub fn apply(&mut self, world: &mut World)

Applies all state queued up for SystemParam values. For example, this will apply commands queued up by a Commands parameter to the given World. This function should be called manually after the values returned by SystemState::get and SystemState::get_mut are finished being used.

source

pub fn matches_world(&self, world_id: WorldId) -> bool

Returns true if world_id matches the World that was used to call SystemState::new. Otherwise, this returns false.

source

pub fn update_archetypes(&mut self, world: &World)

Updates the state’s internal view of the World’s archetypes. If this is not called before fetching the parameters, the results may not accurately reflect what is in the world.

This is only required if SystemState::get_manual or SystemState::get_manual_mut is being called, and it only needs to be called if the world has been structurally mutated (i.e. added/removed a component or resource). Users using SystemState::get or SystemState::get_mut do not need to call this as it will be automatically called for them.

source

pub fn update_archetypes_unsafe_world_cell( &mut self, world: UnsafeWorldCell<'_> )

Updates the state’s internal view of the world’s archetypes. If this is not called before fetching the parameters, the results may not accurately reflect what is in the world.

This is only required if SystemState::get_manual or SystemState::get_manual_mut is being called, and it only needs to be called if the world has been structurally mutated (i.e. added/removed a component or resource). Users using SystemState::get or SystemState::get_mut do not need to call this as it will be automatically called for them.

§Note

This method only accesses world metadata.

source

pub fn get_manual<'w, 's>( &'s mut self, world: &'w World ) -> <Param as SystemParam>::Item<'w, 's>
where Param: ReadOnlySystemParam,

Retrieve the SystemParam values. This can only be called when all parameters are read-only. This will not update the state’s view of the world’s archetypes automatically nor increment the world’s change tick.

For this to return accurate results, ensure SystemState::update_archetypes is called before this function.

Users should strongly prefer to use SystemState::get over this function.

source

pub fn get_manual_mut<'w, 's>( &'s mut self, world: &'w mut World ) -> <Param as SystemParam>::Item<'w, 's>

Retrieve the mutable SystemParam values. This will not update the state’s view of the world’s archetypes automatically nor increment the world’s change tick.

For this to return accurate results, ensure SystemState::update_archetypes is called before this function.

Users should strongly prefer to use SystemState::get_mut over this function.

source

pub unsafe fn get_unchecked_manual<'w, 's>( &'s mut self, world: UnsafeWorldCell<'w> ) -> <Param as SystemParam>::Item<'w, 's>

Retrieve the SystemParam values. This will not update archetypes automatically.

§Safety

This call might access any of the input parameters in a way that violates Rust’s mutability rules. Make sure the data access is safe in the context of global World access. The passed-in World must be the World the SystemState was created with.

Trait Implementations§

source§

impl<'a, P> ExclusiveSystemParam for &'a mut SystemState<P>
where P: SystemParam + 'static,

§

type State = SystemState<P>

Used to store data which persists across invocations of a system.
§

type Item<'s> = &'s mut SystemState<P>

The item type returned when constructing this system param. See SystemParam::Item.
source§

fn init( world: &mut World, _system_meta: &mut SystemMeta ) -> <&'a mut SystemState<P> as ExclusiveSystemParam>::State

Creates a new instance of this param’s State.
source§

fn get_param<'s>( state: &'s mut <&'a mut SystemState<P> as ExclusiveSystemParam>::State, _system_meta: &SystemMeta ) -> <&'a mut SystemState<P> as ExclusiveSystemParam>::Item<'s>

Creates a parameter to be passed into an ExclusiveSystemParamFunction.
source§

impl<Param> FromWorld for SystemState<Param>
where Param: SystemParam,

source§

fn from_world(world: &mut World) -> SystemState<Param>

Creates Self using data from the given World.

Auto Trait Implementations§

§

impl<Param> Freeze for SystemState<Param>
where <Param as SystemParam>::State: Freeze,

§

impl<Param> RefUnwindSafe for SystemState<Param>
where <Param as SystemParam>::State: RefUnwindSafe,

§

impl<Param> Send for SystemState<Param>

§

impl<Param> Sync for SystemState<Param>

§

impl<Param> Unpin for SystemState<Param>
where <Param as SystemParam>::State: Unpin,

§

impl<Param> UnwindSafe for SystemState<Param>
where <Param as SystemParam>::State: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> Downcast<T> for T

source§

fn downcast(&self) -> &T

source§

impl<T> Downcast for T
where T: Any,

source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<S> FromSample<S> for S

source§

fn from_sample_(s: S) -> S

source§

impl<T> Instrument for T

source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

source§

fn to_sample_(self) -> U

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
source§

impl<T> Upcast<T> for T

source§

fn upcast(&self) -> Option<&T>

source§

impl<T> WithSubscriber for T

source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

source§

impl<T> Settings for T
where T: 'static + Send + Sync,

source§

impl<T> WasmNotSend for T
where T: Send,

source§

impl<T> WasmNotSendSync for T

source§

impl<T> WasmNotSync for T
where T: Sync,