Struct bevy::ecs::world::DeferredWorld

pub struct DeferredWorld<'w> { /* private fields */ }
Expand description

A World reference that disallows structural ECS changes. This includes initializing resources, registering components or spawning entities.

Implementations§

§

impl<'w> DeferredWorld<'w>

pub fn reborrow(&mut self) -> DeferredWorld<'_>

Reborrow self as a new instance of DeferredWorld

pub fn commands(&mut self) -> Commands<'_, '_>

Creates a Commands instance that pushes to the world’s command queue

Examples found in repository?
examples/ecs/component_hooks.rs (line 92)
49
50
51
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
fn setup(world: &mut World) {
    // In order to register component hooks the component must:
    // - not be currently in use by any entities in the world
    // - not already have a hook of that kind registered
    // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
    world
        .register_component_hooks::<MyComponent>()
        // There are 3 component lifecycle hooks: `on_add`, `on_insert` and `on_remove`
        // A hook has 3 arguments:
        // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
        // - the entity that triggered the hook
        // - the component id of the triggering component, this is mostly used for dynamic components
        //
        // `on_add` will trigger when a component is inserted onto an entity without it
        .on_add(|mut world, entity, component_id| {
            // You can access component data from within the hook
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} added to: {:?} with value {:?}",
                component_id, entity, value
            );
            // Or access resources
            world
                .resource_mut::<MyComponentIndex>()
                .insert(value, entity);
            // Or send events
            world.send_event(MyEvent);
        })
        // `on_insert` will trigger when a component is inserted onto an entity,
        // regardless of whether or not it already had it and after `on_add` if it ran
        .on_insert(|world, _, _| {
            println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
        })
        // `on_remove` will trigger when a component is removed from an entity,
        // since it runs before the component is removed you can still access the component data
        .on_remove(|mut world, entity, component_id| {
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} removed from: {:?} with value {:?}",
                component_id, entity, value
            );
            world.resource_mut::<MyComponentIndex>().remove(&value);
            // You can also issue commands through `.commands()`
            world.commands().entity(entity).despawn();
        });
}

pub fn get_mut<T>(&mut self, entity: Entity) -> Option<Mut<'_, T>>
where T: Component,

Retrieves a mutable reference to the given entity’s Component of the given type. Returns None if the entity does not have a Component of the given type.

pub fn get_entity_mut(&mut self, entity: Entity) -> Option<EntityMut<'_>>

Retrieves an EntityMut that exposes read and write operations for the given entity. Returns None if the entity does not exist. Instead of unwrapping the value returned from this function, prefer Self::entity_mut.

pub fn entity_mut(&mut self, entity: Entity) -> EntityMut<'_>

Retrieves an EntityMut that exposes read and write operations for the given entity. This will panic if the entity does not exist. Use Self::get_entity_mut if you want to check for entity existence instead of implicitly panic-ing.

pub fn query<'s, D, F>( &'w mut self, state: &'s mut QueryState<D, F>, ) -> Query<'w, 's, D, F>
where D: QueryData, F: QueryFilter,

Returns Query for the given QueryState, which is used to efficiently run queries on the World by storing and reusing the QueryState.

§Panics

If state is from a different world then self

pub fn resource_mut<R>(&mut self) -> Mut<'_, R>
where R: Resource,

Gets a mutable reference to the resource of the given type

§Panics

Panics if the resource does not exist. Use get_resource_mut instead if you want to handle this case.

Examples found in repository?
examples/ecs/component_hooks.rs (line 72)
49
50
51
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
fn setup(world: &mut World) {
    // In order to register component hooks the component must:
    // - not be currently in use by any entities in the world
    // - not already have a hook of that kind registered
    // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
    world
        .register_component_hooks::<MyComponent>()
        // There are 3 component lifecycle hooks: `on_add`, `on_insert` and `on_remove`
        // A hook has 3 arguments:
        // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
        // - the entity that triggered the hook
        // - the component id of the triggering component, this is mostly used for dynamic components
        //
        // `on_add` will trigger when a component is inserted onto an entity without it
        .on_add(|mut world, entity, component_id| {
            // You can access component data from within the hook
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} added to: {:?} with value {:?}",
                component_id, entity, value
            );
            // Or access resources
            world
                .resource_mut::<MyComponentIndex>()
                .insert(value, entity);
            // Or send events
            world.send_event(MyEvent);
        })
        // `on_insert` will trigger when a component is inserted onto an entity,
        // regardless of whether or not it already had it and after `on_add` if it ran
        .on_insert(|world, _, _| {
            println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
        })
        // `on_remove` will trigger when a component is removed from an entity,
        // since it runs before the component is removed you can still access the component data
        .on_remove(|mut world, entity, component_id| {
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} removed from: {:?} with value {:?}",
                component_id, entity, value
            );
            world.resource_mut::<MyComponentIndex>().remove(&value);
            // You can also issue commands through `.commands()`
            world.commands().entity(entity).despawn();
        });
}

pub fn get_resource_mut<R>(&mut self) -> Option<Mut<'_, R>>
where R: Resource,

Gets a mutable reference to the resource of the given type if it exists

pub fn non_send_resource_mut<R>(&mut self) -> Mut<'_, R>
where R: 'static,

Gets a mutable reference to the non-send resource of the given type, if it exists.

§Panics

Panics if the resource does not exist. Use get_non_send_resource_mut instead if you want to handle this case.

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn get_non_send_resource_mut<R>(&mut self) -> Option<Mut<'_, R>>
where R: 'static,

Gets a mutable reference to the non-send resource of the given type, if it exists. Otherwise returns None.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn send_event<E>(&mut self, event: E) -> Option<EventId<E>>
where E: Event,

Sends an Event. This method returns the ID of the sent event, or None if the event could not be sent.

Examples found in repository?
examples/ecs/component_hooks.rs (line 75)
49
50
51
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
fn setup(world: &mut World) {
    // In order to register component hooks the component must:
    // - not be currently in use by any entities in the world
    // - not already have a hook of that kind registered
    // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
    world
        .register_component_hooks::<MyComponent>()
        // There are 3 component lifecycle hooks: `on_add`, `on_insert` and `on_remove`
        // A hook has 3 arguments:
        // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
        // - the entity that triggered the hook
        // - the component id of the triggering component, this is mostly used for dynamic components
        //
        // `on_add` will trigger when a component is inserted onto an entity without it
        .on_add(|mut world, entity, component_id| {
            // You can access component data from within the hook
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} added to: {:?} with value {:?}",
                component_id, entity, value
            );
            // Or access resources
            world
                .resource_mut::<MyComponentIndex>()
                .insert(value, entity);
            // Or send events
            world.send_event(MyEvent);
        })
        // `on_insert` will trigger when a component is inserted onto an entity,
        // regardless of whether or not it already had it and after `on_add` if it ran
        .on_insert(|world, _, _| {
            println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
        })
        // `on_remove` will trigger when a component is removed from an entity,
        // since it runs before the component is removed you can still access the component data
        .on_remove(|mut world, entity, component_id| {
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} removed from: {:?} with value {:?}",
                component_id, entity, value
            );
            world.resource_mut::<MyComponentIndex>().remove(&value);
            // You can also issue commands through `.commands()`
            world.commands().entity(entity).despawn();
        });
}

pub fn send_event_default<E>(&mut self) -> Option<EventId<E>>
where E: Event + Default,

Sends the default value of the Event of type E. This method returns the ID of the sent event, or None if the event could not be sent.

pub fn send_event_batch<E>( &mut self, events: impl IntoIterator<Item = E>, ) -> Option<SendBatchIds<E>>
where E: Event,

Sends a batch of Events from an iterator. This method returns the IDs of the sent events, or None if the event could not be sent.

pub fn get_resource_mut_by_id( &mut self, component_id: ComponentId, ) -> Option<MutUntyped<'_>>

Gets a pointer to the resource with the id ComponentId if it exists. The returned pointer may be used to modify the resource, as long as the mutable borrow of the World is still valid.

You should prefer to use the typed API World::get_resource_mut where possible and only use this in cases where the actual types are not known at compile time.

pub fn get_non_send_mut_by_id( &mut self, component_id: ComponentId, ) -> Option<MutUntyped<'_>>

Gets a !Send resource to the resource with the id ComponentId if it exists. The returned pointer may be used to modify the resource, as long as the mutable borrow of the World is still valid.

You should prefer to use the typed API World::get_resource_mut where possible and only use this in cases where the actual types are not known at compile time.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn get_mut_by_id( &mut self, entity: Entity, component_id: ComponentId, ) -> Option<MutUntyped<'_>>

Retrieves a mutable untyped reference to the given entity’s Component of the given ComponentId. Returns None if the entity does not have a Component of the given type.

You should prefer to use the typed API World::get_mut where possible and only use this in cases where the actual types are not known at compile time.

pub fn trigger<T>(&mut self, trigger: impl Event)
where T: Event,

Sends a “global” [Trigger] without any targets.

pub fn trigger_targets( &mut self, trigger: impl Event, targets: impl TriggerTargets, )

Sends a [Trigger] with the given targets.

Methods from Deref<Target = World>§

pub fn id(&self) -> WorldId

Retrieves this World’s unique ID

pub fn as_unsafe_world_cell_readonly(&self) -> UnsafeWorldCell<'_>

Creates a new UnsafeWorldCell view with only read access to everything.

pub fn entities(&self) -> &Entities

Retrieves this world’s Entities collection.

pub fn archetypes(&self) -> &Archetypes

Retrieves this world’s Archetypes collection.

pub fn components(&self) -> &Components

Retrieves this world’s Components collection.

Examples found in repository?
examples/ecs/dynamic.rs (line 96)
47
48
49
50
51
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
fn main() {
    let mut world = World::new();
    let mut lines = std::io::stdin().lines();
    let mut component_names = HashMap::<String, ComponentId>::new();
    let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();

    println!("{}", PROMPT);
    loop {
        print!("\n> ");
        let _ = std::io::stdout().flush();
        let Some(Ok(line)) = lines.next() else {
            return;
        };

        if line.is_empty() {
            return;
        };

        let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
            match &line.chars().next() {
                Some('c') => println!("{}", COMPONENT_PROMPT),
                Some('s') => println!("{}", ENTITY_PROMPT),
                Some('q') => println!("{}", QUERY_PROMPT),
                _ => println!("{}", PROMPT),
            }
            continue;
        };

        match &first[0..1] {
            "c" => {
                rest.split(',').for_each(|component| {
                    let mut component = component.split_whitespace();
                    let Some(name) = component.next() else {
                        return;
                    };
                    let size = match component.next().map(|s| s.parse::<usize>()) {
                        Some(Ok(size)) => size,
                        _ => 0,
                    };
                    // Register our new component to the world with a layout specified by it's size
                    // SAFETY: [u64] is Send + Sync
                    let id = world.init_component_with_descriptor(unsafe {
                        ComponentDescriptor::new_with_layout(
                            name.to_string(),
                            StorageType::Table,
                            Layout::array::<u64>(size).unwrap(),
                            None,
                        )
                    });
                    let Some(info) = world.components().get_info(id) else {
                        return;
                    };
                    component_names.insert(name.to_string(), id);
                    component_info.insert(id, info.clone());
                    println!("Component {} created with id: {:?}", name, id.index());
                });
            }
            "s" => {
                let mut to_insert_ids = Vec::new();
                let mut to_insert_data = Vec::new();
                rest.split(',').for_each(|component| {
                    let mut component = component.split_whitespace();
                    let Some(name) = component.next() else {
                        return;
                    };

                    // Get the id for the component with the given name
                    let Some(&id) = component_names.get(name) else {
                        println!("Component {} does not exist", name);
                        return;
                    };

                    // Calculate the length for the array based on the layout created for this component id
                    let info = world.components().get_info(id).unwrap();
                    let len = info.layout().size() / std::mem::size_of::<u64>();
                    let mut values: Vec<u64> = component
                        .take(len)
                        .filter_map(|value| value.parse::<u64>().ok())
                        .collect();
                    values.resize(len, 0);

                    // Collect the id and array to be inserted onto our entity
                    to_insert_ids.push(id);
                    to_insert_data.push(values);
                });

                let mut entity = world.spawn_empty();

                // Construct an `OwningPtr` for each component in `to_insert_data`
                let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);

                // SAFETY:
                // - Component ids have been taken from the same world
                // - Each array is created to the layout specified in the world
                unsafe {
                    entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
                }

                println!("Entity spawned with id: {:?}", entity.id());
            }
            "q" => {
                let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
                parse_query(rest, &mut builder, &component_names);
                let mut query = builder.build();

                query.iter_mut(&mut world).for_each(|filtered_entity| {
                    let terms = filtered_entity
                        .components()
                        .map(|id| {
                            let ptr = filtered_entity.get_by_id(id).unwrap();
                            let info = component_info.get(&id).unwrap();
                            let len = info.layout().size() / std::mem::size_of::<u64>();

                            // SAFETY:
                            // - All components are created with layout [u64]
                            // - len is calculated from the component descriptor
                            let data = unsafe {
                                std::slice::from_raw_parts_mut(
                                    ptr.assert_unique().as_ptr().cast::<u64>(),
                                    len,
                                )
                            };

                            // If we have write access, increment each value once
                            if filtered_entity.access().has_write(id) {
                                data.iter_mut().for_each(|data| {
                                    *data += 1;
                                });
                            }

                            format!("{}: {:?}", info.name(), data[0..len].to_vec())
                        })
                        .collect::<Vec<_>>()
                        .join(", ");

                    println!("{:?}: {}", filtered_entity.id(), terms);
                });
            }
            _ => continue,
        }
    }
}

pub fn storages(&self) -> &Storages

Retrieves this world’s Storages collection.

pub fn bundles(&self) -> &Bundles

Retrieves this world’s Bundles collection.

pub fn removed_components(&self) -> &RemovedComponentEvents

Retrieves this world’s RemovedComponentEvents collection

pub fn component_id<T>(&self) -> Option<ComponentId>
where T: Component,

Returns the ComponentId of the given Component type T.

The returned ComponentId is specific to the World instance it was retrieved from and should not be used with another World instance.

Returns None if the Component type has not yet been initialized within the World using World::init_component.

use bevy_ecs::prelude::*;

let mut world = World::new();

#[derive(Component)]
struct ComponentA;

let component_a_id = world.init_component::<ComponentA>();

assert_eq!(component_a_id, world.component_id::<ComponentA>().unwrap())
§See also

pub fn entity(&self, entity: Entity) -> EntityRef<'_>

Retrieves an EntityRef that exposes read-only operations for the given entity. This will panic if the entity does not exist. Use World::get_entity if you want to check for entity existence instead of implicitly panic-ing.

use bevy_ecs::{component::Component, world::World};

#[derive(Component)]
struct Position {
  x: f32,
  y: f32,
}

let mut world = World::new();
let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
let position = world.entity(entity).get::<Position>().unwrap();
assert_eq!(position.x, 0.0);

pub fn inspect_entity(&self, entity: Entity) -> Vec<&ComponentInfo>

Returns the components of an Entity through ComponentInfo.

pub fn get_entity(&self, entity: Entity) -> Option<EntityRef<'_>>

Retrieves an EntityRef that exposes read-only operations for the given entity. Returns None if the entity does not exist. Instead of unwrapping the value returned from this function, prefer World::entity.

use bevy_ecs::{component::Component, world::World};

#[derive(Component)]
struct Position {
  x: f32,
  y: f32,
}

let mut world = World::new();
let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
let entity_ref = world.get_entity(entity).unwrap();
let position = entity_ref.get::<Position>().unwrap();
assert_eq!(position.x, 0.0);

pub fn get_many_entities<const N: usize>( &self, entities: [Entity; N], ) -> Result<[EntityRef<'_>; N], Entity>

Gets an EntityRef for multiple entities at once.

§Errors

If any entity does not exist in the world.

§Examples
// Getting multiple entities.
let [entity1, entity2] = world.get_many_entities([id1, id2]).unwrap();

// Trying to get a despawned entity will fail.
world.despawn(id2);
assert!(world.get_many_entities([id1, id2]).is_err());

pub fn get_many_entities_dynamic<'w>( &'w self, entities: &[Entity], ) -> Result<Vec<EntityRef<'w>>, Entity>

Gets an EntityRef for multiple entities at once, whose number is determined at runtime.

§Errors

If any entity does not exist in the world.

§Examples
// Getting multiple entities.
let entities = world.get_many_entities_dynamic(&[id1, id2]).unwrap();
let entity1 = entities.get(0).unwrap();
let entity2 = entities.get(1).unwrap();

// Trying to get a despawned entity will fail.
world.despawn(id2);
assert!(world.get_many_entities_dynamic(&[id1, id2]).is_err());

pub fn iter_entities(&self) -> impl Iterator<Item = EntityRef<'_>>

Returns an Entity iterator of current entities.

This is useful in contexts where you only have read-only access to the World.

pub fn get<T>(&self, entity: Entity) -> Option<&T>
where T: Component,

Retrieves a reference to the given entity’s Component of the given type. Returns None if the entity does not have a Component of the given type.

use bevy_ecs::{component::Component, world::World};

#[derive(Component)]
struct Position {
  x: f32,
  y: f32,
}

let mut world = World::new();
let entity = world.spawn(Position { x: 0.0, y: 0.0 }).id();
let position = world.get::<Position>(entity).unwrap();
assert_eq!(position.x, 0.0);
Examples found in repository?
examples/ecs/component_hooks.rs (line 65)
49
50
51
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
fn setup(world: &mut World) {
    // In order to register component hooks the component must:
    // - not be currently in use by any entities in the world
    // - not already have a hook of that kind registered
    // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
    world
        .register_component_hooks::<MyComponent>()
        // There are 3 component lifecycle hooks: `on_add`, `on_insert` and `on_remove`
        // A hook has 3 arguments:
        // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
        // - the entity that triggered the hook
        // - the component id of the triggering component, this is mostly used for dynamic components
        //
        // `on_add` will trigger when a component is inserted onto an entity without it
        .on_add(|mut world, entity, component_id| {
            // You can access component data from within the hook
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} added to: {:?} with value {:?}",
                component_id, entity, value
            );
            // Or access resources
            world
                .resource_mut::<MyComponentIndex>()
                .insert(value, entity);
            // Or send events
            world.send_event(MyEvent);
        })
        // `on_insert` will trigger when a component is inserted onto an entity,
        // regardless of whether or not it already had it and after `on_add` if it ran
        .on_insert(|world, _, _| {
            println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
        })
        // `on_remove` will trigger when a component is removed from an entity,
        // since it runs before the component is removed you can still access the component data
        .on_remove(|mut world, entity, component_id| {
            let value = world.get::<MyComponent>(entity).unwrap().0;
            println!(
                "Component: {:?} removed from: {:?} with value {:?}",
                component_id, entity, value
            );
            world.resource_mut::<MyComponentIndex>().remove(&value);
            // You can also issue commands through `.commands()`
            world.commands().entity(entity).despawn();
        });
}

pub fn removed<T>(&self) -> impl Iterator<Item = Entity>
where T: Component,

Returns an iterator of entities that had components of type T removed since the last call to World::clear_trackers.

pub fn removed_with_id( &self, component_id: ComponentId, ) -> impl Iterator<Item = Entity>

Returns an iterator of entities that had components with the given component_id removed since the last call to World::clear_trackers.

pub fn contains_resource<R>(&self) -> bool
where R: Resource,

Returns true if a resource of type R exists. Otherwise returns false.

pub fn contains_non_send<R>(&self) -> bool
where R: 'static,

Returns true if a resource of type R exists. Otherwise returns false.

pub fn is_resource_added<R>(&self) -> bool
where R: Resource,

Returns true if a resource of type R exists and was added since the world’s last_change_tick. Otherwise, this returns false.

This means that:

  • When called from an exclusive system, this will check for additions since the system last ran.
  • When called elsewhere, this will check for additions since the last time that World::clear_trackers was called.

pub fn is_resource_added_by_id(&self, component_id: ComponentId) -> bool

Returns true if a resource with id component_id exists and was added since the world’s last_change_tick. Otherwise, this returns false.

This means that:

  • When called from an exclusive system, this will check for additions since the system last ran.
  • When called elsewhere, this will check for additions since the last time that World::clear_trackers was called.

pub fn is_resource_changed<R>(&self) -> bool
where R: Resource,

Returns true if a resource of type R exists and was modified since the world’s last_change_tick. Otherwise, this returns false.

This means that:

  • When called from an exclusive system, this will check for changes since the system last ran.
  • When called elsewhere, this will check for changes since the last time that World::clear_trackers was called.

pub fn is_resource_changed_by_id(&self, component_id: ComponentId) -> bool

Returns true if a resource with id component_id exists and was modified since the world’s last_change_tick. Otherwise, this returns false.

This means that:

  • When called from an exclusive system, this will check for changes since the system last ran.
  • When called elsewhere, this will check for changes since the last time that World::clear_trackers was called.

pub fn get_resource_change_ticks<R>(&self) -> Option<ComponentTicks>
where R: Resource,

Retrieves the change ticks for the given resource.

pub fn get_resource_change_ticks_by_id( &self, component_id: ComponentId, ) -> Option<ComponentTicks>

Retrieves the change ticks for the given ComponentId.

You should prefer to use the typed API World::get_resource_change_ticks where possible.

pub fn resource<R>(&self) -> &R
where R: Resource,

Gets a reference to the resource of the given type

§Panics

Panics if the resource does not exist. Use get_resource instead if you want to handle this case.

If you want to instead insert a value if the resource does not exist, use get_resource_or_insert_with.

Examples found in repository?
examples/scene/scene.rs (line 46)
45
46
47
48
49
50
51
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
    fn from_world(world: &mut World) -> Self {
        let time = world.resource::<Time>();
        ComponentB {
            _time_since_startup: time.elapsed(),
            value: "Default Value".to_string(),
        }
    }
}

// Resources can be serialized in scenes as well, with the same requirements `Component`s have.
#[derive(Resource, Reflect, Default)]
#[reflect(Resource)]
struct ResourceA {
    pub score: u32,
}

// The initial scene file will be loaded below and not change when the scene is saved
const SCENE_FILE_PATH: &str = "scenes/load_scene_example.scn.ron";

// The new, updated scene data will be saved here so that you can see the changes
const NEW_SCENE_FILE_PATH: &str = "scenes/load_scene_example-new.scn.ron";

fn load_scene_system(mut commands: Commands, asset_server: Res<AssetServer>) {
    // "Spawning" a scene bundle creates a new entity and spawns new instances
    // of the given scene's entities as children of that entity.
    commands.spawn(DynamicSceneBundle {
        // Scenes are loaded just like any other asset.
        scene: asset_server.load(SCENE_FILE_PATH),
        ..default()
    });
}

// This system logs all ComponentA components in our world. Try making a change to a ComponentA in
// load_scene_example.scn. If you enable the `file_watcher` cargo feature you should immediately see
// the changes appear in the console whenever you make a change.
fn log_system(
    query: Query<(Entity, &ComponentA), Changed<ComponentA>>,
    res: Option<Res<ResourceA>>,
) {
    for (entity, component_a) in &query {
        info!("  Entity({})", entity.index());
        info!(
            "    ComponentA: {{ x: {} y: {} }}\n",
            component_a.x, component_a.y
        );
    }
    if let Some(res) = res {
        if res.is_added() {
            info!("  New ResourceA: {{ score: {} }}\n", res.score);
        }
    }
}

fn save_scene_system(world: &mut World) {
    // Scenes can be created from any ECS World.
    // You can either create a new one for the scene or use the current World.
    // For demonstration purposes, we'll create a new one.
    let mut scene_world = World::new();

    // The `TypeRegistry` resource contains information about all registered types (including components).
    // This is used to construct scenes, so we'll want to ensure that our previous type registrations
    // exist in this new scene world as well.
    // To do this, we can simply clone the `AppTypeRegistry` resource.
    let type_registry = world.resource::<AppTypeRegistry>().clone();
    scene_world.insert_resource(type_registry);

    let mut component_b = ComponentB::from_world(world);
    component_b.value = "hello".to_string();
    scene_world.spawn((
        component_b,
        ComponentA { x: 1.0, y: 2.0 },
        Transform::IDENTITY,
        Name::new("joe"),
    ));
    scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
    scene_world.insert_resource(ResourceA { score: 1 });

    // With our sample world ready to go, we can now create our scene using DynamicScene or DynamicSceneBuilder.
    // For simplicity, we will create our scene using DynamicScene:
    let scene = DynamicScene::from_world(&scene_world);

    // Scenes can be serialized like this:
    let type_registry = world.resource::<AppTypeRegistry>();
    let type_registry = type_registry.read();
    let serialized_scene = scene.serialize(&type_registry).unwrap();

    // Showing the scene in the console
    info!("{}", serialized_scene);

    // Writing the scene to a new file. Using a task to avoid calling the filesystem APIs in a system
    // as they are blocking
    // This can't work in WASM as there is no filesystem access
    #[cfg(not(target_arch = "wasm32"))]
    IoTaskPool::get()
        .spawn(async move {
            // Write the scene RON data to file
            File::create(format!("assets/{NEW_SCENE_FILE_PATH}"))
                .and_then(|mut file| file.write(serialized_scene.as_bytes()))
                .expect("Error while writing scene to file");
        })
        .detach();
}
More examples
Hide additional examples
examples/shader/shader_instancing.rs (line 193)
192
193
194
195
196
197
198
199
    fn from_world(world: &mut World) -> Self {
        let mesh_pipeline = world.resource::<MeshPipeline>();

        CustomPipeline {
            shader: world.load_asset(SHADER_ASSET_PATH),
            mesh_pipeline: mesh_pipeline.clone(),
        }
    }
examples/shader/texture_binding_array.rs (line 49)
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    fn finish(&self, app: &mut App) {
        let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
            return;
        };

        let render_device = render_app.world().resource::<RenderDevice>();

        // Check if the device support the required feature. If not, exit the example.
        // In a real application, you should setup a fallback for the missing feature
        if !render_device
            .features()
            .contains(WgpuFeatures::SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING)
        {
            error!(
                "Render device doesn't support feature \
SAMPLED_TEXTURE_AND_STORAGE_BUFFER_ARRAY_NON_UNIFORM_INDEXING, \
which is required for texture binding arrays"
            );
            exit(1);
        }
    }
examples/ecs/ecs_guide.rs (line 207)
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
fn exclusive_player_system(world: &mut World) {
    // this does the same thing as "new_player_system"
    let total_players = world.resource_mut::<GameState>().total_players;
    let should_add_player = {
        let game_rules = world.resource::<GameRules>();
        let add_new_player = random::<bool>();
        add_new_player && total_players < game_rules.max_players
    };
    // Randomly add a new player
    if should_add_player {
        println!("Player {} has joined the game!", total_players + 1);
        world.spawn((
            Player {
                name: format!("Player {}", total_players + 1),
            },
            Score { value: 0 },
        ));

        let mut game_state = world.resource_mut::<GameState>();
        game_state.total_players += 1;
    }
}
examples/shader/gpu_readback.rs (line 112)
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
    fn from_world(world: &mut World) -> Self {
        let render_device = world.resource::<RenderDevice>();
        let render_queue = world.resource::<RenderQueue>();

        // Create the buffer that will be accessed by the gpu
        let mut gpu_buffer = BufferVec::new(BufferUsages::STORAGE | BufferUsages::COPY_SRC);
        for _ in 0..BUFFER_LEN {
            // Init the buffer with zeroes
            gpu_buffer.push(0);
        }
        // Write the buffer so the data is accessible on the gpu
        gpu_buffer.write_buffer(render_device, render_queue);

        // For portability reasons, WebGPU draws a distinction between memory that is
        // accessible by the CPU and memory that is accessible by the GPU. Only
        // buffers accessible by the CPU can be mapped and accessed by the CPU and
        // only buffers visible to the GPU can be used in shaders. In order to get
        // data from the GPU, we need to use `CommandEncoder::copy_buffer_to_buffer` to
        // copy the buffer modified by the GPU into a mappable, CPU-accessible buffer
        let cpu_buffer = render_device.create_buffer(&BufferDescriptor {
            label: Some("readback_buffer"),
            size: (BUFFER_LEN * std::mem::size_of::<u32>()) as u64,
            usage: BufferUsages::MAP_READ | BufferUsages::COPY_DST,
            mapped_at_creation: false,
        });

        Self {
            gpu_buffer,
            cpu_buffer,
        }
    }
}

#[derive(Resource)]
struct GpuBufferBindGroup(BindGroup);

fn prepare_bind_group(
    mut commands: Commands,
    pipeline: Res<ComputePipeline>,
    render_device: Res<RenderDevice>,
    buffers: Res<Buffers>,
) {
    let bind_group = render_device.create_bind_group(
        None,
        &pipeline.layout,
        &BindGroupEntries::single(
            buffers
                .gpu_buffer
                .binding()
                // We already did it when creating the buffer so this should never happen
                .expect("Buffer should have already been uploaded to the gpu"),
        ),
    );
    commands.insert_resource(GpuBufferBindGroup(bind_group));
}

#[derive(Resource)]
struct ComputePipeline {
    layout: BindGroupLayout,
    pipeline: CachedComputePipelineId,
}

impl FromWorld for ComputePipeline {
    fn from_world(world: &mut World) -> Self {
        let render_device = world.resource::<RenderDevice>();
        let layout = render_device.create_bind_group_layout(
            None,
            &BindGroupLayoutEntries::single(
                ShaderStages::COMPUTE,
                storage_buffer::<Vec<u32>>(false),
            ),
        );
        let shader = world.load_asset(SHADER_ASSET_PATH);
        let pipeline_cache = world.resource::<PipelineCache>();
        let pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
            label: Some("GPU readback compute shader".into()),
            layout: vec![layout.clone()],
            push_constant_ranges: Vec::new(),
            shader: shader.clone(),
            shader_defs: Vec::new(),
            entry_point: "main".into(),
        });
        ComputePipeline { layout, pipeline }
    }
}

fn map_and_read_buffer(
    render_device: Res<RenderDevice>,
    buffers: Res<Buffers>,
    sender: Res<RenderWorldSender>,
) {
    // Finally time to get our data back from the gpu.
    // First we get a buffer slice which represents a chunk of the buffer (which we
    // can't access yet).
    // We want the whole thing so use unbounded range.
    let buffer_slice = buffers.cpu_buffer.slice(..);

    // Now things get complicated. WebGPU, for safety reasons, only allows either the GPU
    // or CPU to access a buffer's contents at a time. We need to "map" the buffer which means
    // flipping ownership of the buffer over to the CPU and making access legal. We do this
    // with `BufferSlice::map_async`.
    //
    // The problem is that map_async is not an async function so we can't await it. What
    // we need to do instead is pass in a closure that will be executed when the slice is
    // either mapped or the mapping has failed.
    //
    // The problem with this is that we don't have a reliable way to wait in the main
    // code for the buffer to be mapped and even worse, calling get_mapped_range or
    // get_mapped_range_mut prematurely will cause a panic, not return an error.
    //
    // Using channels solves this as awaiting the receiving of a message from
    // the passed closure will force the outside code to wait. It also doesn't hurt
    // if the closure finishes before the outside code catches up as the message is
    // buffered and receiving will just pick that up.
    //
    // It may also be worth noting that although on native, the usage of asynchronous
    // channels is wholly unnecessary, for the sake of portability to WASM
    // we'll use async channels that work on both native and WASM.

    let (s, r) = crossbeam_channel::unbounded::<()>();

    // Maps the buffer so it can be read on the cpu
    buffer_slice.map_async(MapMode::Read, move |r| match r {
        // This will execute once the gpu is ready, so after the call to poll()
        Ok(_) => s.send(()).expect("Failed to send map update"),
        Err(err) => panic!("Failed to map buffer {err}"),
    });

    // In order for the mapping to be completed, one of three things must happen.
    // One of those can be calling `Device::poll`. This isn't necessary on the web as devices
    // are polled automatically but natively, we need to make sure this happens manually.
    // `Maintain::Wait` will cause the thread to wait on native but not on WebGpu.

    // This blocks until the gpu is done executing everything
    render_device.poll(Maintain::wait()).panic_on_timeout();

    // This blocks until the buffer is mapped
    r.recv().expect("Failed to receive the map_async message");

    {
        let buffer_view = buffer_slice.get_mapped_range();
        let data = buffer_view
            .chunks(std::mem::size_of::<u32>())
            .map(|chunk| u32::from_ne_bytes(chunk.try_into().expect("should be a u32")))
            .collect::<Vec<u32>>();
        sender
            .send(data)
            .expect("Failed to send data to main world");
    }

    // We need to make sure all `BufferView`'s are dropped before we do what we're about
    // to do.
    // Unmap so that we can copy to the staging buffer in the next iteration.
    buffers.cpu_buffer.unmap();
}

/// Label to identify the node in the render graph
#[derive(Debug, Hash, PartialEq, Eq, Clone, RenderLabel)]
struct ComputeNodeLabel;

/// The node that will execute the compute shader
#[derive(Default)]
struct ComputeNode {}
impl render_graph::Node for ComputeNode {
    fn run(
        &self,
        _graph: &mut render_graph::RenderGraphContext,
        render_context: &mut RenderContext,
        world: &World,
    ) -> Result<(), render_graph::NodeRunError> {
        let pipeline_cache = world.resource::<PipelineCache>();
        let pipeline = world.resource::<ComputePipeline>();
        let bind_group = world.resource::<GpuBufferBindGroup>();

        if let Some(init_pipeline) = pipeline_cache.get_compute_pipeline(pipeline.pipeline) {
            let mut pass =
                render_context
                    .command_encoder()
                    .begin_compute_pass(&ComputePassDescriptor {
                        label: Some("GPU readback compute pass"),
                        ..default()
                    });

            pass.set_bind_group(0, &bind_group.0, &[]);
            pass.set_pipeline(init_pipeline);
            pass.dispatch_workgroups(BUFFER_LEN as u32, 1, 1);
        }

        // Copy the gpu accessible buffer to the cpu accessible buffer
        let buffers = world.resource::<Buffers>();
        render_context.command_encoder().copy_buffer_to_buffer(
            buffers
                .gpu_buffer
                .buffer()
                .expect("Buffer should have already been uploaded to the gpu"),
            0,
            &buffers.cpu_buffer,
            0,
            (BUFFER_LEN * std::mem::size_of::<u32>()) as u64,
        );

        Ok(())
    }
examples/shader/compute_shader_game_of_life.rs (line 164)
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
    fn from_world(world: &mut World) -> Self {
        let render_device = world.resource::<RenderDevice>();
        let texture_bind_group_layout = render_device.create_bind_group_layout(
            "GameOfLifeImages",
            &BindGroupLayoutEntries::sequential(
                ShaderStages::COMPUTE,
                (
                    texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::ReadOnly),
                    texture_storage_2d(TextureFormat::R32Float, StorageTextureAccess::WriteOnly),
                ),
            ),
        );
        let shader = world.load_asset(SHADER_ASSET_PATH);
        let pipeline_cache = world.resource::<PipelineCache>();
        let init_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
            label: None,
            layout: vec![texture_bind_group_layout.clone()],
            push_constant_ranges: Vec::new(),
            shader: shader.clone(),
            shader_defs: vec![],
            entry_point: Cow::from("init"),
        });
        let update_pipeline = pipeline_cache.queue_compute_pipeline(ComputePipelineDescriptor {
            label: None,
            layout: vec![texture_bind_group_layout.clone()],
            push_constant_ranges: Vec::new(),
            shader,
            shader_defs: vec![],
            entry_point: Cow::from("update"),
        });

        GameOfLifePipeline {
            texture_bind_group_layout,
            init_pipeline,
            update_pipeline,
        }
    }
}

enum GameOfLifeState {
    Loading,
    Init,
    Update(usize),
}

struct GameOfLifeNode {
    state: GameOfLifeState,
}

impl Default for GameOfLifeNode {
    fn default() -> Self {
        Self {
            state: GameOfLifeState::Loading,
        }
    }
}

impl render_graph::Node for GameOfLifeNode {
    fn update(&mut self, world: &mut World) {
        let pipeline = world.resource::<GameOfLifePipeline>();
        let pipeline_cache = world.resource::<PipelineCache>();

        // if the corresponding pipeline has loaded, transition to the next stage
        match self.state {
            GameOfLifeState::Loading => {
                match pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline) {
                    CachedPipelineState::Ok(_) => {
                        self.state = GameOfLifeState::Init;
                    }
                    CachedPipelineState::Err(err) => {
                        panic!("Initializing assets/{SHADER_ASSET_PATH}:\n{err}")
                    }
                    _ => {}
                }
            }
            GameOfLifeState::Init => {
                if let CachedPipelineState::Ok(_) =
                    pipeline_cache.get_compute_pipeline_state(pipeline.update_pipeline)
                {
                    self.state = GameOfLifeState::Update(1);
                }
            }
            GameOfLifeState::Update(0) => {
                self.state = GameOfLifeState::Update(1);
            }
            GameOfLifeState::Update(1) => {
                self.state = GameOfLifeState::Update(0);
            }
            GameOfLifeState::Update(_) => unreachable!(),
        }
    }

    fn run(
        &self,
        _graph: &mut render_graph::RenderGraphContext,
        render_context: &mut RenderContext,
        world: &World,
    ) -> Result<(), render_graph::NodeRunError> {
        let bind_groups = &world.resource::<GameOfLifeImageBindGroups>().0;
        let pipeline_cache = world.resource::<PipelineCache>();
        let pipeline = world.resource::<GameOfLifePipeline>();

        let mut pass = render_context
            .command_encoder()
            .begin_compute_pass(&ComputePassDescriptor::default());

        // select the pipeline based on the current state
        match self.state {
            GameOfLifeState::Loading => {}
            GameOfLifeState::Init => {
                let init_pipeline = pipeline_cache
                    .get_compute_pipeline(pipeline.init_pipeline)
                    .unwrap();
                pass.set_bind_group(0, &bind_groups[0], &[]);
                pass.set_pipeline(init_pipeline);
                pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
            }
            GameOfLifeState::Update(index) => {
                let update_pipeline = pipeline_cache
                    .get_compute_pipeline(pipeline.update_pipeline)
                    .unwrap();
                pass.set_bind_group(0, &bind_groups[index], &[]);
                pass.set_pipeline(update_pipeline);
                pass.dispatch_workgroups(SIZE.0 / WORKGROUP_SIZE, SIZE.1 / WORKGROUP_SIZE, 1);
            }
        }

        Ok(())
    }

pub fn resource_ref<R>(&self) -> Res<'_, R>
where R: Resource,

Gets a reference to the resource of the given type

§Panics

Panics if the resource does not exist. Use get_resource_ref instead if you want to handle this case.

If you want to instead insert a value if the resource does not exist, use get_resource_or_insert_with.

pub fn get_resource<R>(&self) -> Option<&R>
where R: Resource,

Gets a reference to the resource of the given type if it exists

Examples found in repository?
examples/app/headless_renderer.rs (line 344)
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
    fn run(
        &self,
        _graph: &mut RenderGraphContext,
        render_context: &mut RenderContext,
        world: &World,
    ) -> Result<(), NodeRunError> {
        let image_copiers = world.get_resource::<ImageCopiers>().unwrap();
        let gpu_images = world
            .get_resource::<RenderAssets<bevy::render::texture::GpuImage>>()
            .unwrap();

        for image_copier in image_copiers.iter() {
            if !image_copier.enabled() {
                continue;
            }

            let src_image = gpu_images.get(&image_copier.src_image).unwrap();

            let mut encoder = render_context
                .render_device()
                .create_command_encoder(&CommandEncoderDescriptor::default());

            let block_dimensions = src_image.texture_format.block_dimensions();
            let block_size = src_image.texture_format.block_copy_size(None).unwrap();

            // Calculating correct size of image row because
            // copy_texture_to_buffer can copy image only by rows aligned wgpu::COPY_BYTES_PER_ROW_ALIGNMENT
            // That's why image in buffer can be little bit wider
            // This should be taken into account at copy from buffer stage
            let padded_bytes_per_row = RenderDevice::align_copy_bytes_per_row(
                (src_image.size.x as usize / block_dimensions.0 as usize) * block_size as usize,
            );

            let texture_extent = Extent3d {
                width: src_image.size.x,
                height: src_image.size.y,
                depth_or_array_layers: 1,
            };

            encoder.copy_texture_to_buffer(
                src_image.texture.as_image_copy(),
                ImageCopyBuffer {
                    buffer: &image_copier.buffer,
                    layout: ImageDataLayout {
                        offset: 0,
                        bytes_per_row: Some(
                            std::num::NonZeroU32::new(padded_bytes_per_row as u32)
                                .unwrap()
                                .into(),
                        ),
                        rows_per_image: None,
                    },
                },
                texture_extent,
            );

            let render_queue = world.get_resource::<RenderQueue>().unwrap();
            render_queue.submit(std::iter::once(encoder.finish()));
        }

        Ok(())
    }

pub fn get_resource_ref<R>(&self) -> Option<Res<'_, R>>
where R: Resource,

Gets a reference including change detection to the resource of the given type if it exists.

pub fn non_send_resource<R>(&self) -> &R
where R: 'static,

Gets an immutable reference to the non-send resource of the given type, if it exists.

§Panics

Panics if the resource does not exist. Use get_non_send_resource instead if you want to handle this case.

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn get_non_send_resource<R>(&self) -> Option<&R>
where R: 'static,

Gets a reference to the non-send resource of the given type, if it exists. Otherwise returns None.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn increment_change_tick(&self) -> Tick

Increments the world’s current change tick and returns the old value.

pub fn read_change_tick(&self) -> Tick

Reads the current change tick of this world.

If you have exclusive (&mut) access to the world, consider using change_tick(), which is more efficient since it does not require atomic synchronization.

pub fn last_change_tick(&self) -> Tick

When called from within an exclusive system (a System that takes &mut World as its first parameter), this method returns the Tick indicating the last time the exclusive system was run.

Otherwise, this returns the Tick indicating the last time that World::clear_trackers was called.

pub fn get_resource_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>>

Gets a pointer to the resource with the id ComponentId if it exists. The returned pointer must not be used to modify the resource, and must not be dereferenced after the immutable borrow of the World ends.

You should prefer to use the typed API World::get_resource where possible and only use this in cases where the actual types are not known at compile time.

pub fn iter_resources(&self) -> impl Iterator<Item = (&ComponentInfo, Ptr<'_>)>

Iterates over all resources in the world.

The returned iterator provides lifetimed, but type-unsafe pointers. Actually reading the contents of each resource will require the use of unsafe code.

§Examples
§Printing the size of all resources
let mut total = 0;
for (info, _) in world.iter_resources() {
   println!("Resource: {}", info.name());
   println!("Size: {} bytes", info.layout().size());
   total += info.layout().size();
}
println!("Total size: {} bytes", total);
§Dynamically running closures for resources matching specific TypeIds
// In this example, `A` and `B` are resources. We deliberately do not use the
// `bevy_reflect` crate here to showcase the low-level [`Ptr`] usage. You should
// probably use something like `ReflectFromPtr` in a real-world scenario.

// Create the hash map that will store the closures for each resource type
let mut closures: HashMap<TypeId, Box<dyn Fn(&Ptr<'_>)>> = HashMap::new();

// Add closure for `A`
closures.insert(TypeId::of::<A>(), Box::new(|ptr| {
    // SAFETY: We assert ptr is the same type of A with TypeId of A
    let a = unsafe { &ptr.deref::<A>() };
    // ... do something with `a` here
}));

// Add closure for `B`
closures.insert(TypeId::of::<B>(), Box::new(|ptr| {
    // SAFETY: We assert ptr is the same type of B with TypeId of B
    let b = unsafe { &ptr.deref::<B>() };
    // ... do something with `b` here
}));

// Iterate all resources, in order to run the closures for each matching resource type
for (info, ptr) in world.iter_resources() {
    let Some(type_id) = info.type_id() else {
       // It's possible for resources to not have a `TypeId` (e.g. non-Rust resources
       // dynamically inserted via a scripting language) in which case we can't match them.
       continue;
    };

    let Some(closure) = closures.get(&type_id) else {
       // No closure for this resource type, skip it.
       continue;
    };

    // Run the closure for the resource
    closure(&ptr);
}

pub fn get_non_send_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>>

Gets a !Send resource to the resource with the id ComponentId if it exists. The returned pointer must not be used to modify the resource, and must not be dereferenced after the immutable borrow of the World ends.

You should prefer to use the typed API World::get_resource where possible and only use this in cases where the actual types are not known at compile time.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

pub fn get_by_id( &self, entity: Entity, component_id: ComponentId, ) -> Option<Ptr<'_>>

Retrieves an immutable untyped reference to the given entity’s Component of the given ComponentId. Returns None if the entity does not have a Component of the given type.

You should prefer to use the typed API World::get_mut where possible and only use this in cases where the actual types are not known at compile time.

§Panics

This function will panic if it isn’t called from the same thread that the resource was inserted from.

Trait Implementations§

§

impl<'w> Deref for DeferredWorld<'w>

§

type Target = World

The resulting type after dereferencing.
§

fn deref(&self) -> &<DeferredWorld<'w> as Deref>::Target

Dereferences the value.
§

impl<'w> From<&'w mut World> for DeferredWorld<'w>

§

fn from(world: &'w mut World) -> DeferredWorld<'w>

Converts to this type from the input type.
§

impl<'w> SystemParam for DeferredWorld<'w>

SAFETY: DeferredWorld can read all components and resources but cannot be used to gain any other mutable references.

§

type State = ()

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

type Item<'world, 'state> = DeferredWorld<'world>

The item type returned when constructing this system param. The value of this associated type should be Self, instantiated with new lifetimes. Read more
§

fn init_state( _world: &mut World, system_meta: &mut SystemMeta, ) -> <DeferredWorld<'w> as SystemParam>::State

Registers any World access used by this SystemParam and creates a new instance of this param’s State.
§

unsafe fn get_param<'world, 'state>( _state: &'state mut <DeferredWorld<'w> as SystemParam>::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'world>, _change_tick: Tick, ) -> <DeferredWorld<'w> as SystemParam>::Item<'world, 'state>

Creates a parameter to be passed into a SystemParamFunction. Read more
§

unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, )

For the specified Archetype, registers the components accessed by this SystemParam (if applicable).a Read more
§

fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)

Applies any deferred mutations stored in this SystemParam’s state. This is used to apply Commands during apply_deferred.
§

fn queue( state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )

Queues any deferred mutations to be applied at the next apply_deferred.

Auto Trait Implementations§

§

impl<'w> Freeze for DeferredWorld<'w>

§

impl<'w> !RefUnwindSafe for DeferredWorld<'w>

§

impl<'w> Send for DeferredWorld<'w>

§

impl<'w> Sync for DeferredWorld<'w>

§

impl<'w> Unpin for DeferredWorld<'w>

§

impl<'w> !UnwindSafe for DeferredWorld<'w>

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
§

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

§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> 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
§

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

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

§

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.
§

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.
§

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.
§

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.
§

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

§

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

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.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> Instrument for T

§

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

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

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> IntoEither for T

source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

§

fn into_sample(self) -> T

§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
source§

impl<T> Same for T

§

type Output = T

Should always be Self
§

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

§

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.
§

impl<T> Upcast<T> for T

§

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

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

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

§

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

§

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

§

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

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

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