Struct bevy::ecs::world::World

pub struct World { /* private fields */ }
Expand description

Stores and exposes operations on entities, components, resources, and their associated metadata.

Each Entity has a set of components. Each component can have up to one instance of each component type. Entity components can be created, updated, removed, and queried using a given World.

For complex access patterns involving SystemParam, consider using SystemState.

To mutate different parts of the world simultaneously, use World::resource_scope or SystemState.

§Resources

Worlds can also store Resources, which are unique instances of a given type that don’t belong to a specific Entity. There are also non send resources, which can only be accessed on the main thread. See Resource for usage.

Implementations§

§

impl World

pub fn register_system<I, O, M, S>(&mut self, system: S) -> SystemId<I, O>
where I: 'static, O: 'static, S: IntoSystem<I, O, M> + 'static,

Registers a system and returns a SystemId so it can later be called by World::run_system.

It’s possible to register the same systems more than once, they’ll be stored separately.

This is different from adding systems to a Schedule, because the SystemId that is returned can be used anywhere in the World to run the associated system. This allows for running systems in a pushed-based fashion. Using a Schedule is still preferred for most cases due to its better performance and ability to run non-conflicting systems simultaneously.

Examples found in repository?
examples/ecs/one_shot_systems.rs (line 36)
35
36
37
38
39
40
41
42
fn setup(world: &mut World) {
    let button_pressed_id = world.register_system(button_pressed);
    world.spawn((Callback(button_pressed_id), Triggered));
    // This entity does not have a Triggered component, so its callback won't run.
    let slider_toggled_id = world.register_system(slider_toggled);
    world.spawn(Callback(slider_toggled_id));
    world.run_system_once(count_entities);
}

pub fn register_boxed_system<I, O>( &mut self, system: Box<dyn System<Out = O, In = I>> ) -> SystemId<I, O>
where I: 'static, O: 'static,

Similar to Self::register_system, but allows passing in a BoxedSystem.

This is useful if the IntoSystem implementor has already been turned into a System trait object and put in a Box.

pub fn remove_system<I, O>( &mut self, id: SystemId<I, O> ) -> Result<RemovedSystem<I, O>, RegisteredSystemError<I, O>>
where I: 'static, O: 'static,

Removes a registered system and returns the system, if it exists. After removing a system, the SystemId becomes invalid and attempting to use it afterwards will result in errors. Re-adding the removed system will register it on a new SystemId.

If no system corresponds to the given SystemId, this method returns an error. Systems are also not allowed to remove themselves, this returns an error too.

pub fn run_system<O>( &mut self, id: SystemId<(), O> ) -> Result<O, RegisteredSystemError<(), O>>
where O: 'static,

Run stored systems by their SystemId. Before running a system, it must first be registered. The method World::register_system stores a given system and returns a SystemId. This is different from RunSystemOnce::run_system_once, because it keeps local state between calls and change detection works correctly.

In order to run a chained system with an input, use World::run_system_with_input instead.

§Limitations
§Examples
§Running a system
fn increment(mut counter: Local<u8>) {
   *counter += 1;
   println!("{}", *counter);
}

let mut world = World::default();
let counter_one = world.register_system(increment);
let counter_two = world.register_system(increment);
world.run_system(counter_one); // -> 1
world.run_system(counter_one); // -> 2
world.run_system(counter_two); // -> 1
§Change detection
#[derive(Resource, Default)]
struct ChangeDetector;

let mut world = World::default();
world.init_resource::<ChangeDetector>();
let detector = world.register_system(|change_detector: ResMut<ChangeDetector>| {
    if change_detector.is_changed() {
        println!("Something happened!");
    } else {
        println!("Nothing happened.");
    }
});

// Resources are changed when they are first added
let _ = world.run_system(detector); // -> Something happened!
let _ = world.run_system(detector); // -> Nothing happened.
world.resource_mut::<ChangeDetector>().set_changed();
let _ = world.run_system(detector); // -> Something happened!
§Getting system output

#[derive(Resource)]
struct PlayerScore(i32);

#[derive(Resource)]
struct OpponentScore(i32);

fn get_player_score(player_score: Res<PlayerScore>) -> i32 {
  player_score.0
}

fn get_opponent_score(opponent_score: Res<OpponentScore>) -> i32 {
  opponent_score.0
}

let mut world = World::default();
world.insert_resource(PlayerScore(3));
world.insert_resource(OpponentScore(2));

let scoring_systems = [
  ("player", world.register_system(get_player_score)),
  ("opponent", world.register_system(get_opponent_score)),
];

for (label, scoring_system) in scoring_systems {
  println!("{label} has score {}", world.run_system(scoring_system).expect("system succeeded"));
}

pub fn run_system_with_input<I, O>( &mut self, id: SystemId<I, O>, input: I ) -> Result<O, RegisteredSystemError<I, O>>
where I: 'static, O: 'static,

Run a stored chained system by its SystemId, providing an input value. Before running a system, it must first be registered. The method World::register_system stores a given system and returns a SystemId.

§Limitations
§Examples
fn increment(In(increment_by): In<u8>, mut counter: Local<u8>) -> u8 {
  *counter += increment_by;
  *counter
}

let mut world = World::default();
let counter_one = world.register_system(increment);
let counter_two = world.register_system(increment);
assert_eq!(world.run_system_with_input(counter_one, 1).unwrap(), 1);
assert_eq!(world.run_system_with_input(counter_one, 20).unwrap(), 21);
assert_eq!(world.run_system_with_input(counter_two, 30).unwrap(), 30);

See World::run_system for more examples.

§

impl World

pub fn new() -> World

Creates a new empty World.

§Panics

If usize::MAX Worlds have been created. This guarantee allows System Parameters to safely uniquely identify a World, since its WorldId is unique

Examples found in repository?
examples/scene/scene.rs (line 102)
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 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/ecs/dynamic.rs (line 48)
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 id(&self) -> WorldId

Retrieves this World’s unique ID

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

Creates a new UnsafeWorldCell view with complete read+write access.

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 unsafe fn entities_mut(&mut self) -> &mut Entities

Retrieves this world’s Entities collection mutably.

§Safety

Mutable reference must not be used to put the Entities data in an invalid state for this World

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 commands(&mut self) -> Commands<'_, '_>

Creates a new Commands instance that writes to the world’s command queue Use World::flush_commands to apply all queued commands

pub fn init_component<T>(&mut self) -> ComponentId
where T: Component,

Initializes a new Component type and returns the ComponentId created for it.

pub fn register_component_hooks<T>(&mut self) -> &mut ComponentHooks
where T: Component,

Returns a mutable reference to the ComponentHooks for a Component type.

Will panic if T exists in any archetypes.

Examples found in repository?
examples/ecs/component_hooks.rs (line 55)
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 register_component_hooks_by_id( &mut self, id: ComponentId ) -> Option<&mut ComponentHooks>

Returns a mutable reference to the ComponentHooks for a Component with the given id if it exists.

Will panic if id exists in any archetypes.

pub fn init_component_with_descriptor( &mut self, descriptor: ComponentDescriptor ) -> ComponentId

Initializes a new Component type and returns the ComponentId created for it.

This method differs from World::init_component in that it uses a ComponentDescriptor to initialize the new component type instead of statically available type information. This enables the dynamic initialization of new component definitions at runtime for advanced use cases.

While the option to initialize a component from a descriptor is useful in type-erased contexts, the standard World::init_component function should always be used instead when type information is available at compile time.

Examples found in repository?
examples/ecs/dynamic.rs (lines 88-95)
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 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 entity_mut(&mut self, entity: Entity) -> EntityWorldMut<'_>

Retrieves an EntityWorldMut that exposes read and write operations for the given entity. This will panic if the entity does not exist. Use World::get_entity_mut 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 mut entity_mut = world.entity_mut(entity);
let mut position = entity_mut.get_mut::<Position>().unwrap();
position.x = 1.0;
Examples found in repository?
examples/async_tasks/async_compute.rs (line 89)
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
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));
            }
        }
    }
}

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

Gets an EntityRef for multiple entities at once.

§Panics

If any entity does not exist in the world.

§Examples
// Getting multiple entities.
let [entity1, entity2] = world.many_entities([id1, id2]);
// Trying to get a despawned entity will fail.
world.despawn(id2);
world.many_entities([id1, id2]);

pub fn many_entities_mut<const N: usize>( &mut self, entities: [Entity; N] ) -> [EntityMut<'_>; N]

Gets mutable access to multiple entities at once.

§Panics

If any entities do not exist in the world, or if the same entity is specified multiple times.

§Examples

Disjoint mutable access.

// Disjoint mutable access.
let [entity1, entity2] = world.many_entities_mut([id1, id2]);

Trying to access the same entity multiple times will fail.

world.many_entities_mut([id, id]);

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

Returns the components of an Entity through ComponentInfo.

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

Returns an EntityWorldMut for the given entity (if it exists) or spawns one if it doesn’t exist. This will return None if the entity exists with a different generation.

§Note

Spawning a specific entity value is rarely the right choice. Most apps should favor World::spawn. This method should generally only be used for sharing entities across apps, and only when they have a scheme worked out to share an ID space (which doesn’t happen by default).

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 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 iter_entities_mut(&mut self) -> impl Iterator<Item = EntityMut<'_>>

Returns a mutable iterator over all entities in the World.

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

Retrieves an EntityWorldMut 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 World::entity_mut.

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 mut entity_mut = world.get_entity_mut(entity).unwrap();
let mut position = entity_mut.get_mut::<Position>().unwrap();
position.x = 1.0;

pub fn get_many_entities_mut<const N: usize>( &mut self, entities: [Entity; N] ) -> Result<[EntityMut<'_>; N], QueryEntityError>

Gets mutable access to multiple entities.

§Errors

If any entities do not exist in the world, or if the same entity is specified multiple times.

§Examples
// Disjoint mutable access.
let [entity1, entity2] = world.get_many_entities_mut([id1, id2]).unwrap();

// Trying to access the same entity multiple times will fail.
assert!(world.get_many_entities_mut([id1, id1]).is_err());

pub fn spawn_empty(&mut self) -> EntityWorldMut<'_>

Spawns a new Entity and returns a corresponding EntityWorldMut, which can be used to add components to the entity or retrieve its id.

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

#[derive(Component)]
struct Position {
  x: f32,
  y: f32,
}
#[derive(Component)]
struct Label(&'static str);
#[derive(Component)]
struct Num(u32);

let mut world = World::new();
let entity = world.spawn_empty()
    .insert(Position { x: 0.0, y: 0.0 }) // add a single component
    .insert((Num(1), Label("hello"))) // add a bundle of components
    .id();

let position = world.entity(entity).get::<Position>().unwrap();
assert_eq!(position.x, 0.0);
Examples found in repository?
examples/ecs/dynamic.rs (line 133)
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 spawn<B>(&mut self, bundle: B) -> EntityWorldMut<'_>
where B: Bundle,

Spawns a new Entity with a given Bundle of components and returns a corresponding EntityWorldMut, which can be used to add components to the entity or retrieve its id.

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

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

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

#[derive(Component)]
struct Name(&'static str);

#[derive(Bundle)]
struct PhysicsBundle {
    position: Position,
    velocity: Velocity,
}

let mut world = World::new();

// `spawn` can accept a single component:
world.spawn(Position { x: 0.0, y: 0.0 });
// It can also accept a tuple of components:
world.spawn((
    Position { x: 0.0, y: 0.0 },
    Velocity { x: 1.0, y: 1.0 },
));
// Or it can accept a pre-defined Bundle of components:
world.spawn(PhysicsBundle {
    position: Position { x: 2.0, y: 2.0 },
    velocity: Velocity { x: 0.0, y: 4.0 },
});

let entity = world
    // Tuples can also mix Bundles and Components
    .spawn((
        PhysicsBundle {
            position: Position { x: 2.0, y: 2.0 },
            velocity: Velocity { x: 0.0, y: 4.0 },
        },
        Name("Elaina Proctor"),
    ))
    // Calling id() will return the unique identifier for the spawned entity
    .id();
let position = world.entity(entity).get::<Position>().unwrap();
assert_eq!(position.x, 2.0);
Examples found in repository?
examples/ecs/one_shot_systems.rs (line 37)
35
36
37
38
39
40
41
42
fn setup(world: &mut World) {
    let button_pressed_id = world.register_system(button_pressed);
    world.spawn((Callback(button_pressed_id), Triggered));
    // This entity does not have a Triggered component, so its callback won't run.
    let slider_toggled_id = world.register_system(slider_toggled);
    world.spawn(Callback(slider_toggled_id));
    world.run_system_once(count_entities);
}
More examples
Hide additional examples
examples/ecs/ecs_guide.rs (lines 214-219)
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/scene/scene.rs (lines 113-118)
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 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();
}

pub fn spawn_batch<I>( &mut self, iter: I ) -> SpawnBatchIter<'_, <I as IntoIterator>::IntoIter>
where I: IntoIterator, <I as IntoIterator>::Item: Bundle,

Spawns a batch of entities with the same component Bundle type. Takes a given Bundle iterator and returns a corresponding Entity iterator. This is more efficient than spawning entities and adding components to them individually, but it is limited to spawning entities with the same Bundle type, whereas spawning individually is more flexible.

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

#[derive(Component)]
struct Str(&'static str);
#[derive(Component)]
struct Num(u32);

let mut world = World::new();
let entities = world.spawn_batch(vec![
  (Str("a"), Num(0)), // the first entity
  (Str("b"), Num(1)), // the second entity
]).collect::<Vec<Entity>>();

assert_eq!(entities.len(), 2);

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

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 mut position = world.get_mut::<Position>(entity).unwrap();
position.x = 1.0;

pub fn despawn(&mut self, entity: Entity) -> bool

Despawns the given entity, if it exists. This will also remove all of the entity’s Components. Returns true if the entity is successfully despawned and false if the entity does not exist.

§Note

This won’t clean up external references to the entity (such as parent-child relationships if you’re using bevy_hierarchy), which may leave the world in an invalid state.

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();
assert!(world.despawn(entity));
assert!(world.get_entity(entity).is_none());
assert!(world.get::<Position>(entity).is_none());

pub fn clear_trackers(&mut self)

Clears the internal component tracker state.

The world maintains some internal state about changed and removed components. This state is used by RemovedComponents to provide access to the entities that had a specific type of component removed since last tick.

The state is also used for change detection when accessing components and resources outside of a system, for example via World::get_mut() or World::get_resource_mut().

By clearing this internal state, the world “forgets” about those changes, allowing a new round of detection to be recorded.

When using bevy_ecs as part of the full Bevy engine, this method is added as a system to the main app, to run during Last, so you don’t need to call it manually. When using bevy_ecs as a separate standalone crate however, you need to call this manually.

// a whole new world
let mut world = World::new();

// you changed it
let entity = world.spawn(Transform::default()).id();

// change is detected
let transform = world.get_mut::<Transform>(entity).unwrap();
assert!(transform.is_changed());

// update the last change tick
world.clear_trackers();

// change is no longer detected
let transform = world.get_mut::<Transform>(entity).unwrap();
assert!(!transform.is_changed());

pub fn query<D>(&mut self) -> QueryState<D>
where D: QueryData,

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

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

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

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

let mut world = World::new();
let entities = world.spawn_batch(vec![
    (Position { x: 0.0, y: 0.0}, Velocity { x: 1.0, y: 0.0 }),
    (Position { x: 0.0, y: 0.0}, Velocity { x: 0.0, y: 1.0 }),
]).collect::<Vec<Entity>>();

let mut query = world.query::<(&mut Position, &Velocity)>();
for (mut position, velocity) in query.iter_mut(&mut world) {
   position.x += velocity.x;
   position.y += velocity.y;
}

assert_eq!(world.get::<Position>(entities[0]).unwrap(), &Position { x: 1.0, y: 0.0 });
assert_eq!(world.get::<Position>(entities[1]).unwrap(), &Position { x: 0.0, y: 1.0 });

To iterate over entities in a deterministic order, sort the results of the query using the desired component as a key. Note that this requires fetching the whole result set from the query and allocation of a Vec to store it.

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

#[derive(Component, PartialEq, Eq, PartialOrd, Ord, Debug)]
struct Order(i32);
#[derive(Component, PartialEq, Debug)]
struct Label(&'static str);

let mut world = World::new();
let a = world.spawn((Order(2), Label("second"))).id();
let b = world.spawn((Order(3), Label("third"))).id();
let c = world.spawn((Order(1), Label("first"))).id();
let mut entities = world.query::<(Entity, &Order, &Label)>()
    .iter(&world)
    .collect::<Vec<_>>();
// Sort the query results by their `Order` component before comparing
// to expected results. Query iteration order should not be relied on.
entities.sort_by_key(|e| e.1);
assert_eq!(entities, vec![
    (c, &Order(1), &Label("first")),
    (a, &Order(2), &Label("second")),
    (b, &Order(3), &Label("third")),
]);
Examples found in repository?
examples/tools/scene_viewer/scene_viewer_plugin.rs (line 119)
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
fn scene_load_check(
    asset_server: Res<AssetServer>,
    mut scenes: ResMut<Assets<Scene>>,
    gltf_assets: Res<Assets<Gltf>>,
    mut scene_handle: ResMut<SceneHandle>,
    mut scene_spawner: ResMut<SceneSpawner>,
) {
    match scene_handle.instance_id {
        None => {
            if asset_server.load_state(&scene_handle.gltf_handle) == LoadState::Loaded {
                let gltf = gltf_assets.get(&scene_handle.gltf_handle).unwrap();
                if gltf.scenes.len() > 1 {
                    info!(
                        "Displaying scene {} out of {}",
                        scene_handle.scene_index,
                        gltf.scenes.len()
                    );
                    info!("You can select the scene by adding '#Scene' followed by a number to the end of the file path (e.g '#Scene1' to load the second scene).");
                }

                let gltf_scene_handle =
                    gltf.scenes
                        .get(scene_handle.scene_index)
                        .unwrap_or_else(|| {
                            panic!(
                                "glTF file doesn't contain scene {}!",
                                scene_handle.scene_index
                            )
                        });
                let scene = scenes.get_mut(gltf_scene_handle).unwrap();

                let mut query = scene
                    .world
                    .query::<(Option<&DirectionalLight>, Option<&PointLight>)>();
                scene_handle.has_light =
                    query
                        .iter(&scene.world)
                        .any(|(maybe_directional_light, maybe_point_light)| {
                            maybe_directional_light.is_some() || maybe_point_light.is_some()
                        });

                scene_handle.instance_id =
                    Some(scene_spawner.spawn(gltf_scene_handle.clone_weak()));

                info!("Spawning scene...");
            }
        }
        Some(instance_id) if !scene_handle.is_loaded => {
            if scene_spawner.instance_is_ready(instance_id) {
                info!("...done!");
                scene_handle.is_loaded = true;
            }
        }
        Some(_) => {}
    }
}

pub fn query_filtered<D, F>(&mut self) -> QueryState<D, F>
where D: QueryData, F: QueryFilter,

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

use bevy_ecs::{component::Component, entity::Entity, world::World, query::With};

#[derive(Component)]
struct A;
#[derive(Component)]
struct B;

let mut world = World::new();
let e1 = world.spawn(A).id();
let e2 = world.spawn((A, B)).id();

let mut query = world.query_filtered::<Entity, With<B>>();
let matching_entities = query.iter(&world).collect::<Vec<Entity>>();

assert_eq!(matching_entities, vec![e2]);

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 init_resource<R>(&mut self) -> ComponentId
where R: Resource + FromWorld,

Initializes a new resource and returns the ComponentId created for it.

If the resource already exists, nothing happens.

The value given by the FromWorld::from_world method will be used. Note that any resource with the Default trait automatically implements FromWorld, and those default values will be here instead.

pub fn insert_resource<R>(&mut self, value: R)
where R: Resource,

Inserts a new resource with the given value.

Resources are “unique” data of a given type. If you insert a resource of a type that already exists, you will overwrite any existing data.

Examples found in repository?
examples/scene/scene.rs (line 109)
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 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();
}

pub fn init_non_send_resource<R>(&mut self) -> ComponentId
where R: 'static + FromWorld,

Initializes a new non-send resource and returns the ComponentId created for it.

If the resource already exists, nothing happens.

The value given by the FromWorld::from_world method will be used. Note that any resource with the Default trait automatically implements FromWorld, and those default values will be here instead.

§Panics

Panics if called from a thread other than the main thread.

pub fn insert_non_send_resource<R>(&mut self, value: R)
where R: 'static,

Inserts a new non-send resource with the given value.

NonSend resources cannot be sent across threads, and do not need the Send + Sync bounds. Systems with NonSend resources are always scheduled on the main thread.

§Panics

If a value is already present, this function will panic if called from a different thread than where the original value was inserted from.

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

Removes the resource of a given type and returns it, if it exists. Otherwise returns None.

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

Removes a !Send resource from the world and returns it, if present.

NonSend resources cannot be sent across threads, and do not need the Send + Sync bounds. Systems with NonSend resources are always scheduled on the main thread.

Returns None if a value was not previously present.

§Panics

If a value is present, this function will panic if called from a different thread than where the value was inserted from.

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 185)
184
185
186
187
188
189
190
191
    fn from_world(world: &mut World) -> Self {
        let mesh_pipeline = world.resource::<MeshPipeline>();

        CustomPipeline {
            shader: world.load_asset("shaders/instancing.wgsl"),
            mesh_pipeline: mesh_pipeline.clone(),
        }
    }
examples/shader/texture_binding_array.rs (line 43)
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
    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 105)
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
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
    fn from_world(world: &mut World) -> Self {
        let render_device = world.resource::<RenderDevice>();
        let mut init_data = encase::StorageBuffer::new(Vec::new());
        // Init the buffer with 0
        let data = vec![0; BUFFER_LEN];
        init_data.write(&data).expect("Failed to write buffer");
        // The buffer that will be accessed by the gpu
        let gpu_buffer = render_device.create_buffer_with_data(&BufferInitDescriptor {
            label: Some("gpu_buffer"),
            contents: init_data.as_ref(),
            usage: BufferUsages::STORAGE | BufferUsages::COPY_SRC,
        });
        // 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.as_entire_binding()),
    );
    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("shaders/gpu_readback.wgsl");
        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,
            0,
            &buffers.cpu_buffer,
            0,
            (BUFFER_LEN * std::mem::size_of::<u32>()) as u64,
        );

        Ok(())
    }
examples/shader/compute_shader_game_of_life.rs (line 161)
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
    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("shaders/game_of_life.wgsl");
        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 => {
                if let CachedPipelineState::Ok(_) =
                    pipeline_cache.get_compute_pipeline_state(pipeline.init_pipeline)
                {
                    self.state = GameOfLifeState::Init;
                }
            }
            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 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.

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/app/custom_loop.rs (line 14)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
fn my_runner(mut app: App) -> AppExit {
    println!("Type stuff into the console");
    for line in io::stdin().lines() {
        {
            let mut input = app.world_mut().resource_mut::<Input>();
            input.0 = line.unwrap();
        }
        app.update();

        if let Some(exit) = app.should_exit() {
            return exit;
        }
    }

    AppExit::Success
}
More examples
Hide additional examples
examples/shader/compute_shader_game_of_life.rs (line 110)
100
101
102
103
104
105
106
107
108
109
110
111
112
113
    fn build(&self, app: &mut App) {
        // Extract the game of life image resource from the main world into the render world
        // for operation on by the compute shader and display on the sprite.
        app.add_plugins(ExtractResourcePlugin::<GameOfLifeImages>::default());
        let render_app = app.sub_app_mut(RenderApp);
        render_app.add_systems(
            Render,
            prepare_bind_group.in_set(RenderSet::PrepareBindGroups),
        );

        let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
        render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
        render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
    }
examples/ecs/ecs_guide.rs (line 205)
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/2d/mesh2d_manual.rs (line 275)
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
    fn build(&self, app: &mut App) {
        // Load our custom shader
        let mut shaders = app.world_mut().resource_mut::<Assets<Shader>>();
        shaders.insert(
            &COLORED_MESH2D_SHADER_HANDLE,
            Shader::from_wgsl(COLORED_MESH2D_SHADER, file!()),
        );

        // Register our custom draw function, and add our render systems
        app.get_sub_app_mut(RenderApp)
            .unwrap()
            .add_render_command::<Transparent2d, DrawColoredMesh2d>()
            .init_resource::<SpecializedRenderPipelines<ColoredMesh2dPipeline>>()
            .add_systems(
                ExtractSchedule,
                extract_colored_mesh2d.after(extract_mesh2d),
            )
            .add_systems(Render, queue_colored_mesh2d.in_set(RenderSet::QueueMeshes));
    }
examples/shader/gpu_readback.rs (line 89)
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
    fn finish(&self, app: &mut App) {
        let (s, r) = crossbeam_channel::unbounded();
        app.insert_resource(MainWorldReceiver(r));

        let render_app = app.sub_app_mut(RenderApp);
        render_app
            .insert_resource(RenderWorldSender(s))
            .init_resource::<ComputePipeline>()
            .init_resource::<Buffers>()
            .add_systems(
                Render,
                (
                    prepare_bind_group
                        .in_set(RenderSet::PrepareBindGroups)
                        // We don't need to recreate the bind group every frame
                        .run_if(not(resource_exists::<GpuBufferBindGroup>)),
                    // We need to run it after the render graph is done
                    // because this needs to happen after submit()
                    map_and_read_buffer.after(RenderSet::Render),
                ),
            );

        // Add the compute node as a top level node to the render graph
        // This means it will only execute once per frame
        render_app
            .world_mut()
            .resource_mut::<RenderGraph>()
            .add_node(ComputeNodeLabel, ComputeNode::default());
    }
examples/games/stepping.rs (line 44)
34
35
36
37
38
39
40
41
42
43
44
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
    fn build(&self, app: &mut App) {
        app.add_systems(Startup, build_stepping_hint);
        if cfg!(not(feature = "bevy_debug_stepping")) {
            return;
        }

        // create and insert our debug schedule into the main schedule order.
        // We need an independent schedule so we have access to all other
        // schedules through the `Stepping` resource
        app.init_schedule(DebugSchedule);
        let mut order = app.world_mut().resource_mut::<MainScheduleOrder>();
        order.insert_after(Update, DebugSchedule);

        // create our stepping resource
        let mut stepping = Stepping::new();
        for label in &self.schedule_labels {
            stepping.add_schedule(*label);
        }
        app.insert_resource(stepping);

        // add our startup & stepping systems
        app.insert_resource(State {
            ui_top: self.top,
            ui_left: self.left,
            systems: Vec::new(),
        })
        .add_systems(
            DebugSchedule,
            (
                build_ui.run_if(not(initialized)),
                handle_input,
                update_ui.run_if(initialized),
            )
                .chain(),
        );
    }

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

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

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

Examples found in repository?
examples/games/loading_screen.rs (line 343)
342
343
344
345
346
    fn update_pipelines_ready(mut main_world: ResMut<MainWorld>, pipelines: Res<PipelineCache>) {
        if let Some(mut pipelines_ready) = main_world.get_resource_mut::<PipelinesReady>() {
            pipelines_ready.0 = pipelines.waiting_pipelines().count() == 0;
        }
    }

pub fn get_resource_or_insert_with<R>( &mut self, func: impl FnOnce() -> R ) -> Mut<'_, R>
where R: Resource,

Gets a mutable reference to the resource of type T if it exists, otherwise inserts the resource using the result of calling func.

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 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<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 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 insert_or_spawn_batch<I, B>( &mut self, iter: I ) -> Result<(), Vec<Entity>>
where I: IntoIterator, <I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>, B: Bundle,

For a given batch of (Entity, Bundle) pairs, either spawns each Entity with the given bundle (if the entity does not exist), or inserts the Bundle (if the entity already exists). This is faster than doing equivalent operations one-by-one. Returns Ok if all entities were successfully inserted into or spawned. Otherwise it returns an Err with a list of entities that could not be spawned or inserted into. A “spawn or insert” operation can only fail if an Entity is passed in with an “invalid generation” that conflicts with an existing Entity.

§Note

Spawning a specific entity value is rarely the right choice. Most apps should use World::spawn_batch. This method should generally only be used for sharing entities across apps, and only when they have a scheme worked out to share an ID space (which doesn’t happen by default).

use bevy_ecs::{entity::Entity, world::World, component::Component};
#[derive(Component)]
struct A(&'static str);
#[derive(Component, PartialEq, Debug)]
struct B(f32);

let mut world = World::new();
let e0 = world.spawn_empty().id();
let e1 = world.spawn_empty().id();
world.insert_or_spawn_batch(vec![
  (e0, (A("a"), B(0.0))), // the first entity
  (e1, (A("b"), B(1.0))), // the second entity
]);

assert_eq!(world.get::<B>(e0), Some(&B(0.0)));

pub fn resource_scope<R, U>( &mut self, f: impl FnOnce(&mut World, Mut<'_, R>) -> U ) -> U
where R: Resource,

Temporarily removes the requested resource from this World, runs custom user code, then re-adds the resource before returning.

This enables safe simultaneous mutable access to both a resource and the rest of the World. For more complex access patterns, consider using SystemState.

§Example
use bevy_ecs::prelude::*;
#[derive(Resource)]
struct A(u32);
#[derive(Component)]
struct B(u32);
let mut world = World::new();
world.insert_resource(A(1));
let entity = world.spawn(B(1)).id();

world.resource_scope(|world, mut a: Mut<A>| {
    let b = world.get_mut::<B>(entity).unwrap();
    a.0 += b.0;
});
assert_eq!(world.get_resource::<A>().unwrap().0, 2);

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.

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 unsafe fn insert_resource_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_> )

Inserts a new resource with the given value. Will replace the value if it already existed.

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

§Safety

The value referenced by value must be valid for the given ComponentId of this world.

pub unsafe fn insert_non_send_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_> )

Inserts a new !Send resource with the given value. Will replace the value if it already existed.

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

§Panics

If a value is already present, this function will panic if not called from the same thread that the original value was inserted from.

§Safety

The value referenced by value must be valid for the given ComponentId of this world.

pub fn flush_commands(&mut self)

Applies any commands in the world’s internal CommandQueue. This does not apply commands from any systems, only those stored in the world.

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 change_tick(&mut self) -> Tick

Reads the current change tick of this world.

This does the same thing as read_change_tick(), only this method 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 last_change_tick_scope<T>( &mut self, last_change_tick: Tick, f: impl FnOnce(&mut World) -> T ) -> T

Sets World::last_change_tick() to the specified value during a scope. When the scope terminates, it will return to its old value.

This is useful if you need a region of code to be able to react to earlier changes made in the same system.

§Examples
// This function runs an update loop repeatedly, allowing each iteration of the loop
// to react to changes made in the previous loop iteration.
fn update_loop(
    world: &mut World,
    mut update_fn: impl FnMut(&mut World) -> std::ops::ControlFlow<()>,
) {
    let mut last_change_tick = world.last_change_tick();

    // Repeatedly run the update function until it requests a break.
    loop {
        let control_flow = world.last_change_tick_scope(last_change_tick, |world| {
            // Increment the change tick so we can detect changes from the previous update.
            last_change_tick = world.change_tick();
            world.increment_change_tick();

            // Update once.
            update_fn(world)
        });

        // End the loop when the closure returns `ControlFlow::Break`.
        if control_flow.is_break() {
            break;
        }
    }
}

pub fn check_change_ticks(&mut self)

Iterates all component change ticks and clamps any older than MAX_CHANGE_AGE. This prevents overflow and thus prevents false positives.

Note: Does nothing if the World counter has not been incremented at least CHECK_TICK_THRESHOLD times since the previous pass.

pub fn clear_all(&mut self)

Runs both clear_entities and clear_resources, invalidating all Entity and resource fetches such as Res, ResMut

pub fn clear_entities(&mut self)

Despawns all entities in this World.

pub fn clear_resources(&mut self)

Clears all resources in this World.

Note: Any resource fetch to this World will fail unless they are re-initialized, including engine-internal resources that are only initialized on app/world construction.

This can easily cause systems expecting certain resources to immediately start panicking. Use with caution.

pub fn init_bundle<B>(&mut self) -> &BundleInfo
where B: Bundle,

Initializes all of the components in the given Bundle and returns both the component ids and the bundle id.

This is largely equivalent to calling init_component on each component in the bundle.

§

impl World

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 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 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 iter_resources_mut( &mut self ) -> impl Iterator<Item = (&ComponentInfo, MutUntyped<'_>)>

Mutably iterates over all resources in the world.

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

§Example
// In this example, `A` and `B` are resources. We deliberately do not use the
// `bevy_reflect` crate here to showcase the low-level `MutUntyped` usage. You should
// probably use something like `ReflectFromPtr` in a real-world scenario.

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

// Add mutator closure for `A`
mutators.insert(TypeId::of::<A>(), Box::new(|mut_untyped| {
    // Note: `MutUntyped::as_mut()` automatically marks the resource as changed
    // for ECS change detection, and gives us a `PtrMut` we can use to mutate the resource.
    // SAFETY: We assert ptr is the same type of A with TypeId of A
    let a = unsafe { &mut mut_untyped.as_mut().deref_mut::<A>() };
    // ... mutate `a` here
}));

// Add mutator closure for `B`
mutators.insert(TypeId::of::<B>(), Box::new(|mut_untyped| {
    // SAFETY: We assert ptr is the same type of B with TypeId of B
    let b = unsafe { &mut mut_untyped.as_mut().deref_mut::<B>() };
    // ... mutate `b` here
}));

// Iterate all resources, in order to run the mutator closures for each matching resource type
for (info, mut mut_untyped) in world.iter_resources_mut() {
    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(mutator) = mutators.get(&type_id) else {
       // No mutator closure for this resource type, skip it.
       continue;
    };

    // Run the mutator closure for the resource
    mutator(&mut mut_untyped);
}

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_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 remove_resource_by_id(&mut self, component_id: ComponentId) -> Option<()>

Removes the resource of a given type, if it exists. Otherwise returns None.

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

pub fn remove_non_send_by_id(&mut self, component_id: ComponentId) -> Option<()>

Removes the resource of a given type, if it exists. Otherwise returns None.

You should prefer to use the typed API World::remove_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.

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.

§

impl World

pub fn add_schedule(&mut self, schedule: Schedule)

Adds the specified Schedule to the world. The schedule can later be run by calling .run_schedule(label) or by directly accessing the Schedules resource.

The Schedules resource will be initialized if it does not already exist.

pub fn try_schedule_scope<R>( &mut self, label: impl ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R ) -> Result<R, TryRunScheduleError>

Temporarily removes the schedule associated with label from the world, runs user code, and finally re-adds the schedule. This returns a TryRunScheduleError if there is no schedule associated with label.

The Schedule is fetched from the Schedules resource of the world by its label, and system state is cached.

For simple cases where you just need to call the schedule once, consider using World::try_run_schedule instead. For other use cases, see the example on World::schedule_scope.

pub fn schedule_scope<R>( &mut self, label: impl ScheduleLabel, f: impl FnOnce(&mut World, &mut Schedule) -> R ) -> R

Temporarily removes the schedule associated with label from the world, runs user code, and finally re-adds the schedule.

The Schedule is fetched from the Schedules resource of the world by its label, and system state is cached.

§Examples
// Run the schedule five times.
world.schedule_scope(MySchedule, |world, schedule| {
    for _ in 0..5 {
        schedule.run(world);
    }
});

For simple cases where you just need to call the schedule once, consider using World::run_schedule instead.

§Panics

If the requested schedule does not exist.

pub fn try_run_schedule( &mut self, label: impl ScheduleLabel ) -> Result<(), TryRunScheduleError>

Attempts to run the Schedule associated with the label a single time, and returns a TryRunScheduleError if the schedule does not exist.

The Schedule is fetched from the Schedules resource of the world by its label, and system state is cached.

For simple testing use cases, call Schedule::run(&mut world) instead.

pub fn run_schedule(&mut self, label: impl ScheduleLabel)

Runs the Schedule associated with the label a single time.

The Schedule is fetched from the Schedules resource of the world by its label, and system state is cached.

For simple testing use cases, call Schedule::run(&mut world) instead.

§Panics

If the requested schedule does not exist.

pub fn allow_ambiguous_component<T>(&mut self)
where T: Component,

Ignore system order ambiguities caused by conflicts on Components of type T.

pub fn allow_ambiguous_resource<T>(&mut self)
where T: Resource,

Ignore system order ambiguities caused by conflicts on Resources of type T.

Trait Implementations§

§

impl Debug for World

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
§

impl Default for World

§

fn default() -> World

Returns the “default value” for a type. Read more
§

impl DirectAssetAccessExt for World

§

fn add_asset<'a, A>(&mut self, asset: impl Into<A>) -> Handle<A>
where A: Asset,

Insert an asset similarly to Assets::add.

§Panics

If self doesn’t have an AssetServer resource initialized yet.

§

fn load_asset<'a, A>(&self, path: impl Into<AssetPath<'a>>) -> Handle<A>
where A: Asset,

Load an asset similarly to AssetServer::load.

§Panics

If self doesn’t have an AssetServer resource initialized yet.

§

fn load_asset_with_settings<'a, A, S>( &self, path: impl Into<AssetPath<'a>>, settings: impl Fn(&mut S) + Send + Sync + 'static ) -> Handle<A>
where A: Asset, S: Settings,

Load an asset with settings, similarly to AssetServer::load_with_settings.

§Panics

If self doesn’t have an AssetServer resource initialized yet.

§

impl<F> EntityCommand<World> for F
where F: FnOnce(EntityWorldMut<'_>) + Send + 'static,

§

fn apply(self, id: Entity, world: &mut World)

Executes this command for the given Entity.
§

fn with_entity(self, id: Entity) -> WithEntity<Marker, Self>
where Self: Sized,

Returns a Command which executes this EntityCommand for the given Entity.
§

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 RunSystemOnce for &mut World

§

fn run_system_once_with<T, In, Out, Marker>(self, input: In, system: T) -> Out
where T: IntoSystem<In, Out, Marker>,

Runs a system with given input and applies its deferred parameters.
§

fn run_system_once<T, Out, Marker>(self, system: T) -> Out
where T: IntoSystem<(), Out, Marker>,

Runs a system and applies its deferred parameters.
§

impl SystemParam for &World

§

type State = ()

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

type Item<'w, 's> = &'w 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 ) -> <&World 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<'w, 's>( _state: &'s mut <&World as SystemParam>::State, _system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, _change_tick: Tick ) -> <&World as SystemParam>::Item<'w, 's>

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

impl<'w> ReadOnlySystemParam for &'w World

SAFETY: only reads world

§

impl Send for World

§

impl Sync for World

Auto Trait Implementations§

§

impl !Freeze for World

§

impl !RefUnwindSafe for World

§

impl Unpin for World

§

impl UnwindSafe for World

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

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

impl<T> FromWorld for T
where T: Default,

§

fn from_world(_world: &mut World) -> T

Creates Self using data from the given World.
§

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> NoneValue for T
where T: Default,

§

type NoneType = T

§

fn null_value() -> T

The none-equivalent value.
§

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<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
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,