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 unique components, based on their type.
Entity components can be created, updated, removed, and queried using a given
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 Resource
s,
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§
Source§impl World
impl World
Sourcepub fn add_observer<E, B, M>(
&mut self,
system: impl IntoObserverSystem<E, B, M>,
) -> EntityWorldMut<'_>
pub fn add_observer<E, B, M>( &mut self, system: impl IntoObserverSystem<E, B, M>, ) -> EntityWorldMut<'_>
Spawns a “global” Observer
which will watch for the given event.
Returns its Entity
as a EntityWorldMut
.
Calling observe
on the returned
EntityWorldMut
will observe the observer itself, which you very
likely do not want.
§Example
#[derive(Component)]
struct A;
world.add_observer(|_: Trigger<OnAdd, A>| {
// ...
});
world.add_observer(|_: Trigger<OnRemove, A>| {
// ...
});
Sourcepub fn trigger<E>(&mut self, event: E)where
E: Event,
pub fn trigger<E>(&mut self, event: E)where
E: Event,
Triggers the given Event
, which will run any Observer
s watching for it.
While event types commonly implement Copy
,
those that don’t will be consumed and will no longer be accessible.
If you need to use the event after triggering it, use World::trigger_ref
instead.
Sourcepub fn trigger_ref<E>(&mut self, event: &mut E)where
E: Event,
pub fn trigger_ref<E>(&mut self, event: &mut E)where
E: Event,
Triggers the given Event
as a mutable reference, which will run any Observer
s watching for it.
Compared to World::trigger
, this method is most useful when it’s necessary to check
or use the event after it has been modified by observers.
Sourcepub fn trigger_targets<E>(&mut self, event: E, targets: impl TriggerTargets)where
E: Event,
pub fn trigger_targets<E>(&mut self, event: E, targets: impl TriggerTargets)where
E: Event,
Triggers the given Event
for the given targets
, which will run any Observer
s watching for it.
While event types commonly implement Copy
,
those that don’t will be consumed and will no longer be accessible.
If you need to use the event after triggering it, use World::trigger_targets_ref
instead.
Sourcepub fn trigger_targets_ref<E>(
&mut self,
event: &mut E,
targets: impl TriggerTargets,
)where
E: Event,
pub fn trigger_targets_ref<E>(
&mut self,
event: &mut E,
targets: impl TriggerTargets,
)where
E: Event,
Triggers the given Event
as a mutable reference for the given targets
,
which will run any Observer
s watching for it.
Compared to World::trigger_targets
, this method is most useful when it’s necessary to check
or use the event after it has been modified by observers.
Sourcepub unsafe fn trigger_targets_dynamic<E, Targets>(
&mut self,
event_id: ComponentId,
event_data: E,
targets: Targets,
)where
E: Event,
Targets: TriggerTargets,
pub unsafe fn trigger_targets_dynamic<E, Targets>(
&mut self,
event_id: ComponentId,
event_data: E,
targets: Targets,
)where
E: Event,
Targets: TriggerTargets,
Triggers the given Event
for the given targets
, which will run any Observer
s watching for it.
While event types commonly implement Copy
,
those that don’t will be consumed and will no longer be accessible.
If you need to use the event after triggering it, use World::trigger_targets_dynamic_ref
instead.
§Safety
Caller must ensure that event_data
is accessible as the type represented by event_id
.
Sourcepub unsafe fn trigger_targets_dynamic_ref<E, Targets>(
&mut self,
event_id: ComponentId,
event_data: &mut E,
targets: Targets,
)where
E: Event,
Targets: TriggerTargets,
pub unsafe fn trigger_targets_dynamic_ref<E, Targets>(
&mut self,
event_id: ComponentId,
event_data: &mut E,
targets: Targets,
)where
E: Event,
Targets: TriggerTargets,
Triggers the given Event
as a mutable reference for the given targets
,
which will run any Observer
s watching for it.
Compared to World::trigger_targets_dynamic
, this method is most useful when it’s necessary to check
or use the event after it has been modified by observers.
§Safety
Caller must ensure that event_data
is accessible as the type represented by event_id
.
Source§impl World
impl World
Sourcepub fn register_system<I, O, M>(
&mut self,
system: impl IntoSystem<I, O, M> + 'static,
) -> SystemId<I, O>where
I: SystemInput + 'static,
O: 'static,
pub fn register_system<I, O, M>(
&mut self,
system: impl IntoSystem<I, O, M> + 'static,
) -> SystemId<I, O>where
I: SystemInput + 'static,
O: 'static,
Registers a system and returns a SystemId
so it can later be called by World::run_system
.
It’s possible to register multiple copies of the same system by calling this function
multiple times. If that’s not what you want, consider using World::register_system_cached
instead.
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.
Sourcepub fn register_boxed_system<I, O>(
&mut self,
system: Box<dyn System<Out = O, In = I>>,
) -> SystemId<I, O>where
I: SystemInput + 'static,
O: 'static,
pub fn register_boxed_system<I, O>(
&mut self,
system: Box<dyn System<Out = O, In = I>>,
) -> SystemId<I, O>where
I: SystemInput + '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
.
Sourcepub fn unregister_system<I, O>(
&mut self,
id: SystemId<I, O>,
) -> Result<RemovedSystem<I, O>, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
pub fn unregister_system<I, O>(
&mut self,
id: SystemId<I, O>,
) -> Result<RemovedSystem<I, O>, RegisteredSystemError<I, O>>where
I: SystemInput + '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.
Sourcepub fn run_system<O>(
&mut self,
id: SystemId<(), O>,
) -> Result<O, RegisteredSystemError<(), O>>where
O: 'static,
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.
Also runs any queued-up commands.
In order to run a chained system with an input, use World::run_system_with
instead.
§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"));
}
Sourcepub fn run_system_with<I, O>(
&mut self,
id: SystemId<I, O>,
input: <I as SystemInput>::Inner<'_>,
) -> Result<O, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
pub fn run_system_with<I, O>(
&mut self,
id: SystemId<I, O>,
input: <I as SystemInput>::Inner<'_>,
) -> Result<O, RegisteredSystemError<I, O>>where
I: SystemInput + '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
.
Also runs any queued-up commands.
§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(counter_one, 1).unwrap(), 1);
assert_eq!(world.run_system_with(counter_one, 20).unwrap(), 21);
assert_eq!(world.run_system_with(counter_two, 30).unwrap(), 30);
See World::run_system
for more examples.
Sourcepub fn register_system_cached<I, O, M, S>(
&mut self,
system: S,
) -> SystemId<I, O>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
pub fn register_system_cached<I, O, M, S>(
&mut self,
system: S,
) -> SystemId<I, O>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
Registers a system or returns its cached SystemId
.
If you want to run the system immediately and you don’t need its SystemId
, see
World::run_system_cached
.
The first time this function is called for a particular system, it will register it and
store its SystemId
in a CachedSystemId
resource for later. If you would rather
manage the SystemId
yourself, or register multiple copies of the same system, use
World::register_system
instead.
§Limitations
This function only accepts ZST (zero-sized) systems to guarantee that any two systems of the same type must be equal. This means that closures that capture the environment, and function pointers, are not accepted.
If you want to access values from the environment within a system, consider passing them in
as inputs via World::run_system_cached_with
. If that’s not an option, consider
World::register_system
instead.
Sourcepub fn unregister_system_cached<I, O, M, S>(
&mut self,
_system: S,
) -> Result<RemovedSystem<I, O>, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
pub fn unregister_system_cached<I, O, M, S>(
&mut self,
_system: S,
) -> Result<RemovedSystem<I, O>, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
Removes a cached system and its CachedSystemId
resource.
See World::register_system_cached
for more information.
Sourcepub fn run_system_cached<O, M, S>(
&mut self,
system: S,
) -> Result<O, RegisteredSystemError<(), O>>where
O: 'static,
S: IntoSystem<(), O, M> + 'static,
pub fn run_system_cached<O, M, S>(
&mut self,
system: S,
) -> Result<O, RegisteredSystemError<(), O>>where
O: 'static,
S: IntoSystem<(), O, M> + 'static,
Runs a cached system, registering it if necessary.
See World::register_system_cached
for more information.
Sourcepub fn run_system_cached_with<I, O, M, S>(
&mut self,
system: S,
input: <I as SystemInput>::Inner<'_>,
) -> Result<O, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
pub fn run_system_cached_with<I, O, M, S>(
&mut self,
system: S,
input: <I as SystemInput>::Inner<'_>,
) -> Result<O, RegisteredSystemError<I, O>>where
I: SystemInput + 'static,
O: 'static,
S: IntoSystem<I, O, M> + 'static,
Runs a cached system with an input, registering it if necessary.
See World::register_system_cached
for more information.
Source§impl World
impl World
Sourcepub fn get_reflect(
&self,
entity: Entity,
type_id: TypeId,
) -> Result<&(dyn Reflect + 'static), GetComponentReflectError>
pub fn get_reflect( &self, entity: Entity, type_id: TypeId, ) -> Result<&(dyn Reflect + 'static), GetComponentReflectError>
Retrieves a reference to the given entity
’s Component
of the given type_id
using
reflection.
Requires implementing Reflect
for the Component
(e.g., using #[derive(Reflect)
)
and app.register_type::<TheComponent>()
to have been called1.
If you want to call this with a ComponentId
, see World::components
and Components::get_id
to get
the corresponding TypeId
.
Also see the crate documentation for bevy_reflect
for more information on
Reflect
and bevy’s reflection capabilities.
§Errors
See GetComponentReflectError
for the possible errors and their descriptions.
§Example
use bevy_ecs::prelude::*;
use bevy_reflect::Reflect;
use std::any::TypeId;
// define a `Component` and derive `Reflect` for it
#[derive(Component, Reflect)]
struct MyComponent;
// create a `World` for this example
let mut world = World::new();
// Note: This is usually handled by `App::register_type()`, but this example cannot use `App`.
world.init_resource::<AppTypeRegistry>();
world.get_resource_mut::<AppTypeRegistry>().unwrap().write().register::<MyComponent>();
// spawn an entity with a `MyComponent`
let entity = world.spawn(MyComponent).id();
// retrieve a reflected reference to the entity's `MyComponent`
let comp_reflected: &dyn Reflect = world.get_reflect(entity, TypeId::of::<MyComponent>()).unwrap();
// make sure we got the expected type
assert!(comp_reflected.is::<MyComponent>());
§Note
Requires the bevy_reflect
feature (included in the default features).
More specifically: Requires
TypeData
forReflectFromPtr
to be registered for the giventype_id
, which is automatically handled when derivingReflect
and callingApp::register_type
. ↩
Sourcepub fn get_reflect_mut(
&mut self,
entity: Entity,
type_id: TypeId,
) -> Result<Mut<'_, dyn Reflect>, GetComponentReflectError>
pub fn get_reflect_mut( &mut self, entity: Entity, type_id: TypeId, ) -> Result<Mut<'_, dyn Reflect>, GetComponentReflectError>
Retrieves a mutable reference to the given entity
’s Component
of the given type_id
using
reflection.
Requires implementing Reflect
for the Component
(e.g., using #[derive(Reflect)
)
and app.register_type::<TheComponent>()
to have been called.
This is the mutable version of World::get_reflect
, see its docs for more information
and an example.
Just calling this method does not trigger change detection.
§Errors
See GetComponentReflectError
for the possible errors and their descriptions.
§Example
See the documentation for World::get_reflect
.
§Note
Requires the feature bevy_reflect
(included in the default features).
Source§impl World
impl World
Sourcepub fn new() -> World
pub fn new() -> World
Creates a new empty World
.
§Panics
If usize::MAX
World
s have been created.
This guarantee allows System Parameters to safely uniquely identify a World
,
since its WorldId
is unique
Examples found in repository?
160fn save_scene_system(world: &mut World) {
161 // Scenes can be created from any ECS World.
162 // You can either create a new one for the scene or use the current World.
163 // For demonstration purposes, we'll create a new one.
164 let mut scene_world = World::new();
165
166 // The `TypeRegistry` resource contains information about all registered types (including components).
167 // This is used to construct scenes, so we'll want to ensure that our previous type registrations
168 // exist in this new scene world as well.
169 // To do this, we can simply clone the `AppTypeRegistry` resource.
170 let type_registry = world.resource::<AppTypeRegistry>().clone();
171 scene_world.insert_resource(type_registry);
172
173 let mut component_b = ComponentB::from_world(world);
174 component_b.value = "hello".to_string();
175 scene_world.spawn((
176 component_b,
177 ComponentA { x: 1.0, y: 2.0 },
178 Transform::IDENTITY,
179 Name::new("joe"),
180 ));
181 scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
182 scene_world.insert_resource(ResourceA { score: 1 });
183
184 // With our sample world ready to go, we can now create our scene using DynamicScene or DynamicSceneBuilder.
185 // For simplicity, we will create our scene using DynamicScene:
186 let scene = DynamicScene::from_world(&scene_world);
187
188 // Scenes can be serialized like this:
189 let type_registry = world.resource::<AppTypeRegistry>();
190 let type_registry = type_registry.read();
191 let serialized_scene = scene.serialize(&type_registry).unwrap();
192
193 // Showing the scene in the console
194 info!("{}", serialized_scene);
195
196 // Writing the scene to a new file. Using a task to avoid calling the filesystem APIs in a system
197 // as they are blocking.
198 //
199 // This can't work in Wasm as there is no filesystem access.
200 #[cfg(not(target_arch = "wasm32"))]
201 IoTaskPool::get()
202 .spawn(async move {
203 // Write the scene RON data to file
204 File::create(format!("assets/{NEW_SCENE_FILE_PATH}"))
205 .and_then(|mut file| file.write(serialized_scene.as_bytes()))
206 .expect("Error while writing scene to file");
207 })
208 .detach();
209}
More examples
51fn main() {
52 let mut world = World::new();
53 let mut lines = std::io::stdin().lines();
54 let mut component_names = HashMap::<String, ComponentId>::new();
55 let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();
56
57 println!("{PROMPT}");
58 loop {
59 print!("\n> ");
60 let _ = std::io::stdout().flush();
61 let Some(Ok(line)) = lines.next() else {
62 return;
63 };
64
65 if line.is_empty() {
66 return;
67 };
68
69 let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
70 match &line.chars().next() {
71 Some('c') => println!("{COMPONENT_PROMPT}"),
72 Some('s') => println!("{ENTITY_PROMPT}"),
73 Some('q') => println!("{QUERY_PROMPT}"),
74 _ => println!("{PROMPT}"),
75 }
76 continue;
77 };
78
79 match &first[0..1] {
80 "c" => {
81 rest.split(',').for_each(|component| {
82 let mut component = component.split_whitespace();
83 let Some(name) = component.next() else {
84 return;
85 };
86 let size = match component.next().map(str::parse) {
87 Some(Ok(size)) => size,
88 _ => 0,
89 };
90 // Register our new component to the world with a layout specified by it's size
91 // SAFETY: [u64] is Send + Sync
92 let id = world.register_component_with_descriptor(unsafe {
93 ComponentDescriptor::new_with_layout(
94 name.to_string(),
95 StorageType::Table,
96 Layout::array::<u64>(size).unwrap(),
97 None,
98 true,
99 ComponentCloneBehavior::Default,
100 )
101 });
102 let Some(info) = world.components().get_info(id) else {
103 return;
104 };
105 component_names.insert(name.to_string(), id);
106 component_info.insert(id, info.clone());
107 println!("Component {} created with id: {}", name, id.index());
108 });
109 }
110 "s" => {
111 let mut to_insert_ids = Vec::new();
112 let mut to_insert_data = Vec::new();
113 rest.split(',').for_each(|component| {
114 let mut component = component.split_whitespace();
115 let Some(name) = component.next() else {
116 return;
117 };
118
119 // Get the id for the component with the given name
120 let Some(&id) = component_names.get(name) else {
121 println!("Component {name} does not exist");
122 return;
123 };
124
125 // Calculate the length for the array based on the layout created for this component id
126 let info = world.components().get_info(id).unwrap();
127 let len = info.layout().size() / size_of::<u64>();
128 let mut values: Vec<u64> = component
129 .take(len)
130 .filter_map(|value| value.parse::<u64>().ok())
131 .collect();
132 values.resize(len, 0);
133
134 // Collect the id and array to be inserted onto our entity
135 to_insert_ids.push(id);
136 to_insert_data.push(values);
137 });
138
139 let mut entity = world.spawn_empty();
140
141 // Construct an `OwningPtr` for each component in `to_insert_data`
142 let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);
143
144 // SAFETY:
145 // - Component ids have been taken from the same world
146 // - Each array is created to the layout specified in the world
147 unsafe {
148 entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
149 }
150
151 println!("Entity spawned with id: {}", entity.id());
152 }
153 "q" => {
154 let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
155 parse_query(rest, &mut builder, &component_names);
156 let mut query = builder.build();
157 query.iter_mut(&mut world).for_each(|filtered_entity| {
158 let terms = filtered_entity
159 .access()
160 .try_iter_component_access()
161 .unwrap()
162 .map(|component_access| {
163 let id = *component_access.index();
164 let ptr = filtered_entity.get_by_id(id).unwrap();
165 let info = component_info.get(&id).unwrap();
166 let len = info.layout().size() / size_of::<u64>();
167
168 // SAFETY:
169 // - All components are created with layout [u64]
170 // - len is calculated from the component descriptor
171 let data = unsafe {
172 std::slice::from_raw_parts_mut(
173 ptr.assert_unique().as_ptr().cast::<u64>(),
174 len,
175 )
176 };
177
178 // If we have write access, increment each value once
179 if matches!(component_access, ComponentAccessKind::Exclusive(_)) {
180 data.iter_mut().for_each(|data| {
181 *data += 1;
182 });
183 }
184
185 format!("{}: {:?}", info.name(), data[0..len].to_vec())
186 })
187 .collect::<Vec<_>>()
188 .join(", ");
189
190 println!("{}: {}", filtered_entity.id(), terms);
191 });
192 }
193 _ => continue,
194 }
195 }
196}
36fn main() {
37 // Operating on a raw `World` and running systems one at a time
38 // is great for writing tests and teaching abstract concepts!
39 let mut world = World::new();
40
41 // We're going to spawn a few entities and relate them to each other in a complex way.
42 // To start, Bob will target Alice, Charlie will target Bob,
43 // and Alice will target Charlie. This creates a loop in the relationship graph.
44 //
45 // Then, we'll spawn Devon, who will target Charlie,
46 // creating a more complex graph with a branching structure.
47 fn spawning_entities_with_relationships(mut commands: Commands) {
48 // Calling .id() after spawning an entity will return the `Entity` identifier of the spawned entity,
49 // even though the entity itself is not yet instantiated in the world.
50 // This works because Commands will reserve the entity ID before actually spawning the entity,
51 // through the use of atomic counters.
52 let alice = commands.spawn(Name::new("Alice")).id();
53 // Relations are just components, so we can add them into the bundle that we're spawning.
54 let bob = commands.spawn((Name::new("Bob"), Targeting(alice))).id();
55
56 // The `with_related` and `with_relationships` helper methods on `EntityCommands` can be used to add relations in a more ergonomic way.
57 let charlie = commands
58 .spawn((Name::new("Charlie"), Targeting(bob)))
59 // The `with_related` method will spawn a bundle with `Targeting` relationship
60 .with_related::<Targeting>(Name::new("James"))
61 // The `with_relationships` method will automatically add the `Targeting` component to any entities spawned within the closure,
62 // targeting the entity that we're calling `with_related` on.
63 .with_related_entities::<Targeting>(|related_spawner_commands| {
64 // We could spawn multiple entities here, and they would all target `charlie`.
65 related_spawner_commands.spawn(Name::new("Devon"));
66 })
67 .id();
68
69 // Simply inserting the `Targeting` component will automatically create and update the `TargetedBy` component on the target entity.
70 // We can do this at any point; not just when the entity is spawned.
71 commands.entity(alice).insert(Targeting(charlie));
72 }
73
74 world
75 .run_system_once(spawning_entities_with_relationships)
76 .unwrap();
77
78 fn debug_relationships(
79 // Not all of our entities are targeted by something, so we use `Option` in our query to handle this case.
80 relations_query: Query<(&Name, &Targeting, Option<&TargetedBy>)>,
81 name_query: Query<&Name>,
82 ) {
83 let mut relationships = String::new();
84
85 for (name, targeting, maybe_targeted_by) in relations_query.iter() {
86 let targeting_name = name_query.get(targeting.0).unwrap();
87 let targeted_by_string = if let Some(targeted_by) = maybe_targeted_by {
88 let mut vec_of_names = Vec::<&Name>::new();
89
90 for entity in &targeted_by.0 {
91 let name = name_query.get(*entity).unwrap();
92 vec_of_names.push(name);
93 }
94
95 // Convert this to a nice string for printing.
96 let vec_of_str: Vec<&str> = vec_of_names.iter().map(|name| name.as_str()).collect();
97 vec_of_str.join(", ")
98 } else {
99 "nobody".to_string()
100 };
101
102 relationships.push_str(&format!(
103 "{name} is targeting {targeting_name}, and is targeted by {targeted_by_string}\n",
104 ));
105 }
106
107 println!("{}", relationships);
108 }
109
110 world.run_system_once(debug_relationships).unwrap();
111
112 // Demonstrates how to correctly mutate relationships.
113 // Relationship components are immutable! We can't query for the `Targeting` component mutably and modify it directly,
114 // but we can insert a new `Targeting` component to replace the old one.
115 // This allows the hooks on the `Targeting` component to update the `TargetedBy` component correctly.
116 // The `TargetedBy` component will be updated automatically!
117 fn mutate_relationships(name_query: Query<(Entity, &Name)>, mut commands: Commands) {
118 // Let's find Devon by doing a linear scan of the entity names.
119 let devon = name_query
120 .iter()
121 .find(|(_entity, name)| name.as_str() == "Devon")
122 .unwrap()
123 .0;
124
125 let alice = name_query
126 .iter()
127 .find(|(_entity, name)| name.as_str() == "Alice")
128 .unwrap()
129 .0;
130
131 println!("Making Devon target Alice.\n");
132 commands.entity(devon).insert(Targeting(alice));
133 }
134
135 world.run_system_once(mutate_relationships).unwrap();
136 world.run_system_once(debug_relationships).unwrap();
137
138 // Systems can return errors,
139 // which can be used to signal that something went wrong during the system's execution.
140 #[derive(Debug)]
141 #[expect(
142 dead_code,
143 reason = "Rust considers types that are only used by their debug trait as dead code."
144 )]
145 struct TargetingCycle {
146 initial_entity: Entity,
147 visited: EntityHashSet,
148 }
149
150 /// Bevy's relationships come with all sorts of useful methods for traversal.
151 /// Here, we're going to look for cycles using a depth-first search.
152 fn check_for_cycles(
153 // We want to check every entity for cycles
154 query_to_check: Query<Entity, With<Targeting>>,
155 // Fetch the names for easier debugging.
156 name_query: Query<&Name>,
157 // The targeting_query allows us to traverse the relationship graph.
158 targeting_query: Query<&Targeting>,
159 ) -> Result<(), TargetingCycle> {
160 for initial_entity in query_to_check.iter() {
161 let mut visited = EntityHashSet::new();
162 let mut targeting_name = name_query.get(initial_entity).unwrap().clone();
163 println!("Checking for cycles starting at {targeting_name}",);
164
165 // There's all sorts of methods like this; check the `Query` docs for more!
166 // This would also be easy to do by just manually checking the `Targeting` component,
167 // and calling `query.get(targeted_entity)` on the entity that it targets in a loop.
168 for targeting in targeting_query.iter_ancestors(initial_entity) {
169 let target_name = name_query.get(targeting).unwrap();
170 println!("{targeting_name} is targeting {target_name}",);
171 targeting_name = target_name.clone();
172
173 if !visited.insert(targeting) {
174 return Err(TargetingCycle {
175 initial_entity,
176 visited,
177 });
178 }
179 }
180 }
181
182 // If we've checked all the entities and haven't found a cycle, we're good!
183 Ok(())
184 }
185
186 // Calling `world.run_system_once` on systems which return Results gives us two layers of errors:
187 // the first checks if running the system failed, and the second checks if the system itself returned an error.
188 // We're unwrapping the first, but checking the output of the system itself.
189 let cycle_result = world.run_system_once(check_for_cycles).unwrap();
190 println!("{cycle_result:?} \n");
191 // We deliberately introduced a cycle during spawning!
192 assert!(cycle_result.is_err());
193
194 // Now, let's demonstrate removing relationships and break the cycle.
195 fn untarget(mut commands: Commands, name_query: Query<(Entity, &Name)>) {
196 // Let's find Charlie by doing a linear scan of the entity names.
197 let charlie = name_query
198 .iter()
199 .find(|(_entity, name)| name.as_str() == "Charlie")
200 .unwrap()
201 .0;
202
203 // We can remove the `Targeting` component to remove the relationship
204 // and break the cycle we saw earlier.
205 println!("Removing Charlie's targeting relationship.\n");
206 commands.entity(charlie).remove::<Targeting>();
207 }
208
209 world.run_system_once(untarget).unwrap();
210 world.run_system_once(debug_relationships).unwrap();
211 // Cycle free!
212 let cycle_result = world.run_system_once(check_for_cycles).unwrap();
213 println!("{cycle_result:?} \n");
214 assert!(cycle_result.is_ok());
215}
Sourcepub fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell<'_>
pub fn as_unsafe_world_cell(&mut self) -> UnsafeWorldCell<'_>
Creates a new UnsafeWorldCell
view with complete read+write access.
Sourcepub fn as_unsafe_world_cell_readonly(&self) -> UnsafeWorldCell<'_>
pub fn as_unsafe_world_cell_readonly(&self) -> UnsafeWorldCell<'_>
Creates a new UnsafeWorldCell
view with only read access to everything.
Sourcepub unsafe fn entities_mut(&mut self) -> &mut Entities
pub unsafe fn entities_mut(&mut self) -> &mut Entities
Sourcepub fn archetypes(&self) -> &Archetypes
pub fn archetypes(&self) -> &Archetypes
Retrieves this world’s Archetypes
collection.
Examples found in repository?
79fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
80 let mut rng = ChaCha8Rng::seed_from_u64(42);
81 let mut app = App::default();
82 let world = app.world_mut();
83
84 // register a bunch of components
85 let component_ids: Vec<ComponentId> = (1..=num_components)
86 .map(|i| {
87 world.register_component_with_descriptor(
88 // SAFETY:
89 // * We don't implement a drop function
90 // * u8 is Sync and Send
91 unsafe {
92 ComponentDescriptor::new_with_layout(
93 format!("Component{}", i).to_string(),
94 StorageType::Table,
95 Layout::new::<u8>(),
96 None,
97 true, // is mutable
98 ComponentCloneBehavior::Default,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.gen_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .choose_multiple(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.gen_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .choose_multiple(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.gen_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 println!(
161 "Number of Archetype-Components: {}",
162 world.archetypes().archetype_components_len()
163 );
164
165 // overwrite Update schedule in the app
166 app.add_schedule(schedule);
167 app.add_plugins(MinimalPlugins)
168 .add_plugins(DiagnosticsPlugin)
169 .add_plugins(LogPlugin::default())
170 .add_plugins(FrameTimeDiagnosticsPlugin::default())
171 .add_plugins(LogDiagnosticsPlugin::filtered(vec![DiagnosticPath::new(
172 "fps",
173 )]));
174 app.run();
175}
Sourcepub fn components(&self) -> &Components
pub fn components(&self) -> &Components
Retrieves this world’s Components
collection.
Examples found in repository?
51fn main() {
52 let mut world = World::new();
53 let mut lines = std::io::stdin().lines();
54 let mut component_names = HashMap::<String, ComponentId>::new();
55 let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();
56
57 println!("{PROMPT}");
58 loop {
59 print!("\n> ");
60 let _ = std::io::stdout().flush();
61 let Some(Ok(line)) = lines.next() else {
62 return;
63 };
64
65 if line.is_empty() {
66 return;
67 };
68
69 let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
70 match &line.chars().next() {
71 Some('c') => println!("{COMPONENT_PROMPT}"),
72 Some('s') => println!("{ENTITY_PROMPT}"),
73 Some('q') => println!("{QUERY_PROMPT}"),
74 _ => println!("{PROMPT}"),
75 }
76 continue;
77 };
78
79 match &first[0..1] {
80 "c" => {
81 rest.split(',').for_each(|component| {
82 let mut component = component.split_whitespace();
83 let Some(name) = component.next() else {
84 return;
85 };
86 let size = match component.next().map(str::parse) {
87 Some(Ok(size)) => size,
88 _ => 0,
89 };
90 // Register our new component to the world with a layout specified by it's size
91 // SAFETY: [u64] is Send + Sync
92 let id = world.register_component_with_descriptor(unsafe {
93 ComponentDescriptor::new_with_layout(
94 name.to_string(),
95 StorageType::Table,
96 Layout::array::<u64>(size).unwrap(),
97 None,
98 true,
99 ComponentCloneBehavior::Default,
100 )
101 });
102 let Some(info) = world.components().get_info(id) else {
103 return;
104 };
105 component_names.insert(name.to_string(), id);
106 component_info.insert(id, info.clone());
107 println!("Component {} created with id: {}", name, id.index());
108 });
109 }
110 "s" => {
111 let mut to_insert_ids = Vec::new();
112 let mut to_insert_data = Vec::new();
113 rest.split(',').for_each(|component| {
114 let mut component = component.split_whitespace();
115 let Some(name) = component.next() else {
116 return;
117 };
118
119 // Get the id for the component with the given name
120 let Some(&id) = component_names.get(name) else {
121 println!("Component {name} does not exist");
122 return;
123 };
124
125 // Calculate the length for the array based on the layout created for this component id
126 let info = world.components().get_info(id).unwrap();
127 let len = info.layout().size() / size_of::<u64>();
128 let mut values: Vec<u64> = component
129 .take(len)
130 .filter_map(|value| value.parse::<u64>().ok())
131 .collect();
132 values.resize(len, 0);
133
134 // Collect the id and array to be inserted onto our entity
135 to_insert_ids.push(id);
136 to_insert_data.push(values);
137 });
138
139 let mut entity = world.spawn_empty();
140
141 // Construct an `OwningPtr` for each component in `to_insert_data`
142 let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);
143
144 // SAFETY:
145 // - Component ids have been taken from the same world
146 // - Each array is created to the layout specified in the world
147 unsafe {
148 entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
149 }
150
151 println!("Entity spawned with id: {}", entity.id());
152 }
153 "q" => {
154 let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
155 parse_query(rest, &mut builder, &component_names);
156 let mut query = builder.build();
157 query.iter_mut(&mut world).for_each(|filtered_entity| {
158 let terms = filtered_entity
159 .access()
160 .try_iter_component_access()
161 .unwrap()
162 .map(|component_access| {
163 let id = *component_access.index();
164 let ptr = filtered_entity.get_by_id(id).unwrap();
165 let info = component_info.get(&id).unwrap();
166 let len = info.layout().size() / size_of::<u64>();
167
168 // SAFETY:
169 // - All components are created with layout [u64]
170 // - len is calculated from the component descriptor
171 let data = unsafe {
172 std::slice::from_raw_parts_mut(
173 ptr.assert_unique().as_ptr().cast::<u64>(),
174 len,
175 )
176 };
177
178 // If we have write access, increment each value once
179 if matches!(component_access, ComponentAccessKind::Exclusive(_)) {
180 data.iter_mut().for_each(|data| {
181 *data += 1;
182 });
183 }
184
185 format!("{}: {:?}", info.name(), data[0..len].to_vec())
186 })
187 .collect::<Vec<_>>()
188 .join(", ");
189
190 println!("{}: {}", filtered_entity.id(), terms);
191 });
192 }
193 _ => continue,
194 }
195 }
196}
Sourcepub fn components_queue(&self) -> ComponentsQueuedRegistrator<'_>
pub fn components_queue(&self) -> ComponentsQueuedRegistrator<'_>
Prepares a ComponentsQueuedRegistrator
for the world.
NOTE: ComponentsQueuedRegistrator
is easily misused.
See its docs for important notes on when and how it should be used.
Sourcepub fn components_registrator(&mut self) -> ComponentsRegistrator<'_>
pub fn components_registrator(&mut self) -> ComponentsRegistrator<'_>
Prepares a ComponentsRegistrator
for the world.
Sourcepub fn removed_components(&self) -> &RemovedComponentEvents
pub fn removed_components(&self) -> &RemovedComponentEvents
Retrieves this world’s RemovedComponentEvents
collection
Sourcepub fn commands(&mut self) -> Commands<'_, '_>
pub fn commands(&mut self) -> Commands<'_, '_>
Creates a new Commands
instance that writes to the world’s command queue
Use World::flush
to apply all queued commands
Sourcepub fn register_component<T>(&mut self) -> ComponentIdwhere
T: Component,
pub fn register_component<T>(&mut self) -> ComponentIdwhere
T: Component,
Registers a new Component
type and returns the ComponentId
created for it.
§Usage Notes
In most cases, you don’t need to call this method directly since component registration happens automatically during system initialization.
Sourcepub fn register_disabling_component<C>(&mut self)where
C: Component,
pub fn register_disabling_component<C>(&mut self)where
C: Component,
Registers a component type as “disabling”, using default query filters to exclude entities with the component from queries.
Sourcepub fn register_component_hooks<T>(&mut self) -> &mut ComponentHookswhere
T: Component,
pub fn register_component_hooks<T>(&mut self) -> &mut ComponentHookswhere
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?
60fn setup(world: &mut World) {
61 // In order to register component hooks the component must:
62 // - not be currently in use by any entities in the world
63 // - not already have a hook of that kind registered
64 // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
65 world
66 .register_component_hooks::<MyComponent>()
67 // There are 4 component lifecycle hooks: `on_add`, `on_insert`, `on_replace` and `on_remove`
68 // A hook has 2 arguments:
69 // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
70 // - a `HookContext`, this provides access to the following contextual information:
71 // - the entity that triggered the hook
72 // - the component id of the triggering component, this is mostly used for dynamic components
73 // - the location of the code that caused the hook to trigger
74 //
75 // `on_add` will trigger when a component is inserted onto an entity without it
76 .on_add(
77 |mut world,
78 HookContext {
79 entity,
80 component_id,
81 caller,
82 ..
83 }| {
84 // You can access component data from within the hook
85 let value = world.get::<MyComponent>(entity).unwrap().0;
86 println!(
87 "{component_id:?} added to {entity} with value {value:?}{}",
88 caller
89 .map(|location| format!("due to {location}"))
90 .unwrap_or_default()
91 );
92 // Or access resources
93 world
94 .resource_mut::<MyComponentIndex>()
95 .insert(value, entity);
96 // Or send events
97 world.send_event(MyEvent);
98 },
99 )
100 // `on_insert` will trigger when a component is inserted onto an entity,
101 // regardless of whether or not it already had it and after `on_add` if it ran
102 .on_insert(|world, _| {
103 println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
104 })
105 // `on_replace` will trigger when a component is inserted onto an entity that already had it,
106 // and runs before the value is replaced.
107 // Also triggers when a component is removed from an entity, and runs before `on_remove`
108 .on_replace(|mut world, context| {
109 let value = world.get::<MyComponent>(context.entity).unwrap().0;
110 world.resource_mut::<MyComponentIndex>().remove(&value);
111 })
112 // `on_remove` will trigger when a component is removed from an entity,
113 // since it runs before the component is removed you can still access the component data
114 .on_remove(
115 |mut world,
116 HookContext {
117 entity,
118 component_id,
119 caller,
120 ..
121 }| {
122 let value = world.get::<MyComponent>(entity).unwrap().0;
123 println!(
124 "{component_id:?} removed from {entity} with value {value:?}{}",
125 caller
126 .map(|location| format!("due to {location}"))
127 .unwrap_or_default()
128 );
129 // You can also issue commands through `.commands()`
130 world.commands().entity(entity).despawn();
131 },
132 );
133}
Sourcepub fn register_component_hooks_by_id(
&mut self,
id: ComponentId,
) -> Option<&mut ComponentHooks>
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.
Sourcepub fn register_required_components<T, R>(&mut self)
pub fn register_required_components<T, R>(&mut self)
Registers the given component R
as a required component for T
.
When T
is added to an entity, R
and its own required components will also be added
if R
was not already provided. The Default
constructor
will be used for the creation of R
.
If a custom constructor is desired, use World::register_required_components_with
instead.
For the non-panicking version, see World::try_register_required_components
.
Note that requirements must currently be registered before T
is inserted into the world
for the first time. This limitation may be fixed in the future.
§Panics
Panics if R
is already a directly required component for T
, or if T
has ever been added
on an entity before the registration.
Indirect requirements through other components are allowed. In those cases, any existing requirements will only be overwritten if the new requirement is more specific.
§Example
#[derive(Component)]
struct A;
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct B(usize);
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct C(u32);
// Register B as required by A and C as required by B.
world.register_required_components::<A, B>();
world.register_required_components::<B, C>();
// This will implicitly also insert B and C with their Default constructors.
let id = world.spawn(A).id();
assert_eq!(&B(0), world.entity(id).get::<B>().unwrap());
assert_eq!(&C(0), world.entity(id).get::<C>().unwrap());
Sourcepub fn register_required_components_with<T, R>(
&mut self,
constructor: fn() -> R,
)
pub fn register_required_components_with<T, R>( &mut self, constructor: fn() -> R, )
Registers the given component R
as a required component for T
.
When T
is added to an entity, R
and its own required components will also be added
if R
was not already provided. The given constructor
will be used for the creation of R
.
If a Default
constructor is desired, use World::register_required_components
instead.
For the non-panicking version, see World::try_register_required_components_with
.
Note that requirements must currently be registered before T
is inserted into the world
for the first time. This limitation may be fixed in the future.
§Panics
Panics if R
is already a directly required component for T
, or if T
has ever been added
on an entity before the registration.
Indirect requirements through other components are allowed. In those cases, any existing requirements will only be overwritten if the new requirement is more specific.
§Example
#[derive(Component)]
struct A;
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct B(usize);
#[derive(Component, PartialEq, Eq, Debug)]
struct C(u32);
// Register B and C as required by A and C as required by B.
// A requiring C directly will overwrite the indirect requirement through B.
world.register_required_components::<A, B>();
world.register_required_components_with::<B, C>(|| C(1));
world.register_required_components_with::<A, C>(|| C(2));
// This will implicitly also insert B with its Default constructor and C
// with the custom constructor defined by A.
let id = world.spawn(A).id();
assert_eq!(&B(0), world.entity(id).get::<B>().unwrap());
assert_eq!(&C(2), world.entity(id).get::<C>().unwrap());
Sourcepub fn try_register_required_components<T, R>(
&mut self,
) -> Result<(), RequiredComponentsError>
pub fn try_register_required_components<T, R>( &mut self, ) -> Result<(), RequiredComponentsError>
Tries to register the given component R
as a required component for T
.
When T
is added to an entity, R
and its own required components will also be added
if R
was not already provided. The Default
constructor
will be used for the creation of R
.
If a custom constructor is desired, use World::register_required_components_with
instead.
For the panicking version, see World::register_required_components
.
Note that requirements must currently be registered before T
is inserted into the world
for the first time. This limitation may be fixed in the future.
§Errors
Returns a RequiredComponentsError
if R
is already a directly required component for T
, or if T
has ever been added
on an entity before the registration.
Indirect requirements through other components are allowed. In those cases, any existing requirements will only be overwritten if the new requirement is more specific.
§Example
#[derive(Component)]
struct A;
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct B(usize);
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct C(u32);
// Register B as required by A and C as required by B.
world.register_required_components::<A, B>();
world.register_required_components::<B, C>();
// Duplicate registration! This will fail.
assert!(world.try_register_required_components::<A, B>().is_err());
// This will implicitly also insert B and C with their Default constructors.
let id = world.spawn(A).id();
assert_eq!(&B(0), world.entity(id).get::<B>().unwrap());
assert_eq!(&C(0), world.entity(id).get::<C>().unwrap());
Sourcepub fn try_register_required_components_with<T, R>(
&mut self,
constructor: fn() -> R,
) -> Result<(), RequiredComponentsError>
pub fn try_register_required_components_with<T, R>( &mut self, constructor: fn() -> R, ) -> Result<(), RequiredComponentsError>
Tries to register the given component R
as a required component for T
.
When T
is added to an entity, R
and its own required components will also be added
if R
was not already provided. The given constructor
will be used for the creation of R
.
If a Default
constructor is desired, use World::register_required_components
instead.
For the panicking version, see World::register_required_components_with
.
Note that requirements must currently be registered before T
is inserted into the world
for the first time. This limitation may be fixed in the future.
§Errors
Returns a RequiredComponentsError
if R
is already a directly required component for T
, or if T
has ever been added
on an entity before the registration.
Indirect requirements through other components are allowed. In those cases, any existing requirements will only be overwritten if the new requirement is more specific.
§Example
#[derive(Component)]
struct A;
#[derive(Component, Default, PartialEq, Eq, Debug)]
struct B(usize);
#[derive(Component, PartialEq, Eq, Debug)]
struct C(u32);
// Register B and C as required by A and C as required by B.
// A requiring C directly will overwrite the indirect requirement through B.
world.register_required_components::<A, B>();
world.register_required_components_with::<B, C>(|| C(1));
world.register_required_components_with::<A, C>(|| C(2));
// Duplicate registration! Even if the constructors were different, this would fail.
assert!(world.try_register_required_components_with::<B, C>(|| C(1)).is_err());
// This will implicitly also insert B with its Default constructor and C
// with the custom constructor defined by A.
let id = world.spawn(A).id();
assert_eq!(&B(0), world.entity(id).get::<B>().unwrap());
assert_eq!(&C(2), world.entity(id).get::<C>().unwrap());
Sourcepub fn get_required_components<C>(&self) -> Option<&RequiredComponents>where
C: Component,
pub fn get_required_components<C>(&self) -> Option<&RequiredComponents>where
C: Component,
Retrieves the required components for the given component type, if it exists.
Sourcepub fn get_required_components_by_id(
&self,
id: ComponentId,
) -> Option<&RequiredComponents>
pub fn get_required_components_by_id( &self, id: ComponentId, ) -> Option<&RequiredComponents>
Retrieves the required components for the component of the given ComponentId
, if it exists.
Sourcepub fn register_component_with_descriptor(
&mut self,
descriptor: ComponentDescriptor,
) -> ComponentId
pub fn register_component_with_descriptor( &mut self, descriptor: ComponentDescriptor, ) -> ComponentId
Registers a new Component
type and returns the ComponentId
created for it.
This method differs from World::register_component
in that it uses a ComponentDescriptor
to register the new component type instead of statically available type information. This
enables the dynamic registration of new component definitions at runtime for advanced use cases.
While the option to register a component from a descriptor is useful in type-erased
contexts, the standard World::register_component
function should always be used instead
when type information is available at compile time.
Examples found in repository?
136fn demo_3(world: &mut World) {
137 // This is a list of dynamic components we will create.
138 // The first item is the name of the component, and the second is the size
139 // in bytes.
140 let my_dynamic_components = [("Foo", 1), ("Bar", 2), ("Baz", 4)];
141
142 // This pipeline takes our component descriptions, registers them, and gets
143 // their ComponentId's.
144 let my_registered_components = my_dynamic_components
145 .into_iter()
146 .map(|(name, size)| {
147 // SAFETY:
148 // - No drop command is required
149 // - The component will store [u8; size], which is Send + Sync
150 let descriptor = unsafe {
151 ComponentDescriptor::new_with_layout(
152 name.to_string(),
153 StorageType::Table,
154 Layout::array::<u8>(size).unwrap(),
155 None,
156 false,
157 ComponentCloneBehavior::Default,
158 )
159 };
160
161 (name, size, descriptor)
162 })
163 .map(|(name, size, descriptor)| {
164 let component_id = world.register_component_with_descriptor(descriptor);
165
166 (name, size, component_id)
167 })
168 .collect::<Vec<(&str, usize, ComponentId)>>();
169
170 // Now that our components are registered, let's add them to an entity
171 let mut entity = world.spawn_empty();
172
173 for (_name, size, component_id) in &my_registered_components {
174 // We're just storing some zeroes for the sake of demonstration.
175 let data = core::iter::repeat_n(0, *size).collect::<Vec<u8>>();
176
177 OwningPtr::make(data, |ptr| {
178 // SAFETY:
179 // - ComponentId has been taken from the same world
180 // - Array is created to the layout specified in the world
181 unsafe {
182 entity.insert_by_id(*component_id, ptr);
183 }
184 });
185 }
186
187 for (_name, _size, component_id) in &my_registered_components {
188 // With immutable components, we can read the values...
189 assert!(entity.get_by_id(*component_id).is_ok());
190
191 // ...but we cannot gain a mutable reference.
192 assert!(entity.get_mut_by_id(*component_id).is_err());
193
194 // Instead, you must either remove or replace the value.
195 }
196}
More examples
79fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
80 let mut rng = ChaCha8Rng::seed_from_u64(42);
81 let mut app = App::default();
82 let world = app.world_mut();
83
84 // register a bunch of components
85 let component_ids: Vec<ComponentId> = (1..=num_components)
86 .map(|i| {
87 world.register_component_with_descriptor(
88 // SAFETY:
89 // * We don't implement a drop function
90 // * u8 is Sync and Send
91 unsafe {
92 ComponentDescriptor::new_with_layout(
93 format!("Component{}", i).to_string(),
94 StorageType::Table,
95 Layout::new::<u8>(),
96 None,
97 true, // is mutable
98 ComponentCloneBehavior::Default,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.gen_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .choose_multiple(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.gen_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .choose_multiple(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.gen_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 println!(
161 "Number of Archetype-Components: {}",
162 world.archetypes().archetype_components_len()
163 );
164
165 // overwrite Update schedule in the app
166 app.add_schedule(schedule);
167 app.add_plugins(MinimalPlugins)
168 .add_plugins(DiagnosticsPlugin)
169 .add_plugins(LogPlugin::default())
170 .add_plugins(FrameTimeDiagnosticsPlugin::default())
171 .add_plugins(LogDiagnosticsPlugin::filtered(vec![DiagnosticPath::new(
172 "fps",
173 )]));
174 app.run();
175}
51fn main() {
52 let mut world = World::new();
53 let mut lines = std::io::stdin().lines();
54 let mut component_names = HashMap::<String, ComponentId>::new();
55 let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();
56
57 println!("{PROMPT}");
58 loop {
59 print!("\n> ");
60 let _ = std::io::stdout().flush();
61 let Some(Ok(line)) = lines.next() else {
62 return;
63 };
64
65 if line.is_empty() {
66 return;
67 };
68
69 let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
70 match &line.chars().next() {
71 Some('c') => println!("{COMPONENT_PROMPT}"),
72 Some('s') => println!("{ENTITY_PROMPT}"),
73 Some('q') => println!("{QUERY_PROMPT}"),
74 _ => println!("{PROMPT}"),
75 }
76 continue;
77 };
78
79 match &first[0..1] {
80 "c" => {
81 rest.split(',').for_each(|component| {
82 let mut component = component.split_whitespace();
83 let Some(name) = component.next() else {
84 return;
85 };
86 let size = match component.next().map(str::parse) {
87 Some(Ok(size)) => size,
88 _ => 0,
89 };
90 // Register our new component to the world with a layout specified by it's size
91 // SAFETY: [u64] is Send + Sync
92 let id = world.register_component_with_descriptor(unsafe {
93 ComponentDescriptor::new_with_layout(
94 name.to_string(),
95 StorageType::Table,
96 Layout::array::<u64>(size).unwrap(),
97 None,
98 true,
99 ComponentCloneBehavior::Default,
100 )
101 });
102 let Some(info) = world.components().get_info(id) else {
103 return;
104 };
105 component_names.insert(name.to_string(), id);
106 component_info.insert(id, info.clone());
107 println!("Component {} created with id: {}", name, id.index());
108 });
109 }
110 "s" => {
111 let mut to_insert_ids = Vec::new();
112 let mut to_insert_data = Vec::new();
113 rest.split(',').for_each(|component| {
114 let mut component = component.split_whitespace();
115 let Some(name) = component.next() else {
116 return;
117 };
118
119 // Get the id for the component with the given name
120 let Some(&id) = component_names.get(name) else {
121 println!("Component {name} does not exist");
122 return;
123 };
124
125 // Calculate the length for the array based on the layout created for this component id
126 let info = world.components().get_info(id).unwrap();
127 let len = info.layout().size() / size_of::<u64>();
128 let mut values: Vec<u64> = component
129 .take(len)
130 .filter_map(|value| value.parse::<u64>().ok())
131 .collect();
132 values.resize(len, 0);
133
134 // Collect the id and array to be inserted onto our entity
135 to_insert_ids.push(id);
136 to_insert_data.push(values);
137 });
138
139 let mut entity = world.spawn_empty();
140
141 // Construct an `OwningPtr` for each component in `to_insert_data`
142 let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);
143
144 // SAFETY:
145 // - Component ids have been taken from the same world
146 // - Each array is created to the layout specified in the world
147 unsafe {
148 entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
149 }
150
151 println!("Entity spawned with id: {}", entity.id());
152 }
153 "q" => {
154 let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
155 parse_query(rest, &mut builder, &component_names);
156 let mut query = builder.build();
157 query.iter_mut(&mut world).for_each(|filtered_entity| {
158 let terms = filtered_entity
159 .access()
160 .try_iter_component_access()
161 .unwrap()
162 .map(|component_access| {
163 let id = *component_access.index();
164 let ptr = filtered_entity.get_by_id(id).unwrap();
165 let info = component_info.get(&id).unwrap();
166 let len = info.layout().size() / size_of::<u64>();
167
168 // SAFETY:
169 // - All components are created with layout [u64]
170 // - len is calculated from the component descriptor
171 let data = unsafe {
172 std::slice::from_raw_parts_mut(
173 ptr.assert_unique().as_ptr().cast::<u64>(),
174 len,
175 )
176 };
177
178 // If we have write access, increment each value once
179 if matches!(component_access, ComponentAccessKind::Exclusive(_)) {
180 data.iter_mut().for_each(|data| {
181 *data += 1;
182 });
183 }
184
185 format!("{}: {:?}", info.name(), data[0..len].to_vec())
186 })
187 .collect::<Vec<_>>()
188 .join(", ");
189
190 println!("{}: {}", filtered_entity.id(), terms);
191 });
192 }
193 _ => continue,
194 }
195 }
196}
Sourcepub fn component_id<T>(&self) -> Option<ComponentId>where
T: Component,
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::register_component
.
use bevy_ecs::prelude::*;
let mut world = World::new();
#[derive(Component)]
struct ComponentA;
let component_a_id = world.register_component::<ComponentA>();
assert_eq!(component_a_id, world.component_id::<ComponentA>().unwrap())
§See also
Sourcepub fn register_resource<R>(&mut self) -> ComponentIdwhere
R: Resource,
pub fn register_resource<R>(&mut self) -> ComponentIdwhere
R: Resource,
Registers a new Resource
type and returns the ComponentId
created for it.
The Resource
doesn’t have a value in the World
, it’s only registered. If you want
to insert the Resource
in the World
, use World::init_resource
or
World::insert_resource
instead.
Sourcepub fn resource_id<T>(&self) -> Option<ComponentId>where
T: Resource,
pub fn resource_id<T>(&self) -> Option<ComponentId>where
T: Resource,
Returns the ComponentId
of the given Resource
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 Resource
type has not yet been initialized within the
World
using World::register_resource
, World::init_resource
or World::insert_resource
.
Sourcepub fn entity<F>(&self, entities: F) -> <F as WorldEntityFetch>::Ref<'_>where
F: WorldEntityFetch,
pub fn entity<F>(&self, entities: F) -> <F as WorldEntityFetch>::Ref<'_>where
F: WorldEntityFetch,
Returns EntityRef
s that expose read-only operations for the given
entities
. This will panic if any of the given entities do not exist. Use
World::get_entity
if you want to check for entity existence instead
of implicitly panicking.
This function supports fetching a single entity or multiple entities:
- Pass an
Entity
to receive a singleEntityRef
. - Pass a slice of
Entity
s to receive aVec<EntityRef>
. - Pass an array of
Entity
s to receive an equally-sized array ofEntityRef
s.
§Panics
If any of the given entities
do not exist in the world.
§Examples
§Single Entity
#[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);
§Array of Entity
s
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 0.0 }).id();
let e2 = world.spawn(Position { x: 1.0, y: 1.0 }).id();
let [e1_ref, e2_ref] = world.entity([e1, e2]);
let e1_position = e1_ref.get::<Position>().unwrap();
assert_eq!(e1_position.x, 0.0);
let e2_position = e2_ref.get::<Position>().unwrap();
assert_eq!(e2_position.x, 1.0);
§Slice of Entity
s
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let ids = vec![e1, e2, e3];
for eref in world.entity(&ids[..]) {
assert_eq!(eref.get::<Position>().unwrap().y, 1.0);
}
§EntityHashSet
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let ids = EntityHashSet::from_iter([e1, e2, e3]);
for (_id, eref) in world.entity(&ids) {
assert_eq!(eref.get::<Position>().unwrap().y, 1.0);
}
Examples found in repository?
78fn on_insert_name(mut world: DeferredWorld<'_>, HookContext { entity, .. }: HookContext) {
79 let Some(&name) = world.entity(entity).get::<Name>() else {
80 unreachable!("OnInsert hook guarantees `Name` is available on entity")
81 };
82 let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
83 return;
84 };
85
86 index.name_to_entity.insert(name, entity);
87}
88
89/// When a [`Name`] is removed or replaced, remove it from our [`NameIndex`].
90///
91/// Since all mutations to [`Name`] are captured by hooks, we know it is currently
92/// inserted in the index.
93fn on_replace_name(mut world: DeferredWorld<'_>, HookContext { entity, .. }: HookContext) {
94 let Some(&name) = world.entity(entity).get::<Name>() else {
95 unreachable!("OnReplace hook guarantees `Name` is available on entity")
96 };
97 let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
98 return;
99 };
100
101 index.name_to_entity.remove(&name);
102}
Sourcepub fn entity_mut<F>(&mut self, entities: F) -> <F as WorldEntityFetch>::Mut<'_>where
F: WorldEntityFetch,
pub fn entity_mut<F>(&mut self, entities: F) -> <F as WorldEntityFetch>::Mut<'_>where
F: WorldEntityFetch,
Returns EntityMut
s that expose read and write operations for the
given entities
. This will panic if any of the given entities do not
exist. Use World::get_entity_mut
if you want to check for entity
existence instead of implicitly panicking.
This function supports fetching a single entity or multiple entities:
- Pass an
Entity
to receive a singleEntityWorldMut
.- This reference type allows for structural changes to the entity, such as adding or removing components, or despawning the entity.
- Pass a slice of
Entity
s to receive aVec<EntityMut>
. - Pass an array of
Entity
s to receive an equally-sized array ofEntityMut
s. - Pass a reference to a
EntityHashSet
to receive anEntityHashMap<EntityMut>
.
In order to perform structural changes on the returned entity reference,
such as adding or removing components, or despawning the entity, only a
single Entity
can be passed to this function. Allowing multiple
entities at the same time with structural access would lead to undefined
behavior, so EntityMut
is returned when requesting multiple entities.
§Panics
If any of the given entities
do not exist in the world.
§Examples
§Single Entity
#[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.y = 1.0;
assert_eq!(position.x, 0.0);
entity_mut.despawn();
§Array of Entity
s
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 0.0 }).id();
let e2 = world.spawn(Position { x: 1.0, y: 1.0 }).id();
let [mut e1_ref, mut e2_ref] = world.entity_mut([e1, e2]);
let mut e1_position = e1_ref.get_mut::<Position>().unwrap();
e1_position.x = 1.0;
assert_eq!(e1_position.x, 1.0);
let mut e2_position = e2_ref.get_mut::<Position>().unwrap();
e2_position.x = 2.0;
assert_eq!(e2_position.x, 2.0);
§Slice of Entity
s
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let ids = vec![e1, e2, e3];
for mut eref in world.entity_mut(&ids[..]) {
let mut pos = eref.get_mut::<Position>().unwrap();
pos.y = 2.0;
assert_eq!(pos.y, 2.0);
}
§EntityHashSet
#[derive(Component)]
struct Position {
x: f32,
y: f32,
}
let mut world = World::new();
let e1 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e2 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let e3 = world.spawn(Position { x: 0.0, y: 1.0 }).id();
let ids = EntityHashSet::from_iter([e1, e2, e3]);
for (_id, mut eref) in world.entity_mut(&ids) {
let mut pos = eref.get_mut::<Position>().unwrap();
pos.y = 2.0;
assert_eq!(pos.y, 2.0);
}
Examples found in repository?
104fn demo_2(world: &mut World) {
105 // Setup our name index
106 world.init_resource::<NameIndex>();
107
108 // Spawn some entities!
109 let alyssa = world.spawn(Name("Alyssa")).id();
110 let javier = world.spawn(Name("Javier")).id();
111
112 // Check our index
113 let index = world.resource::<NameIndex>();
114
115 assert_eq!(index.get_entity("Alyssa"), Some(alyssa));
116 assert_eq!(index.get_entity("Javier"), Some(javier));
117
118 // Changing the name of an entity is also fully capture by our index
119 world.entity_mut(javier).insert(Name("Steven"));
120
121 // Javier changed their name to Steven
122 let steven = javier;
123
124 // Check our index
125 let index = world.resource::<NameIndex>();
126
127 assert_eq!(index.get_entity("Javier"), None);
128 assert_eq!(index.get_entity("Steven"), Some(steven));
129}
More examples
52fn spawn_tasks(mut commands: Commands) {
53 let thread_pool = AsyncComputeTaskPool::get();
54 for x in 0..NUM_CUBES {
55 for y in 0..NUM_CUBES {
56 for z in 0..NUM_CUBES {
57 // Spawn new task on the AsyncComputeTaskPool; the task will be
58 // executed in the background, and the Task future returned by
59 // spawn() can be used to poll for the result
60 let entity = commands.spawn_empty().id();
61 let task = thread_pool.spawn(async move {
62 let duration = Duration::from_secs_f32(rand::thread_rng().gen_range(0.05..5.0));
63
64 // Pretend this is a time-intensive function. :)
65 async_std::task::sleep(duration).await;
66
67 // Such hard work, all done!
68 let transform = Transform::from_xyz(x as f32, y as f32, z as f32);
69 let mut command_queue = CommandQueue::default();
70
71 // we use a raw command queue to pass a FnOnce(&mut World) back to be
72 // applied in a deferred manner.
73 command_queue.push(move |world: &mut World| {
74 let (box_mesh_handle, box_material_handle) = {
75 let mut system_state = SystemState::<(
76 Res<BoxMeshHandle>,
77 Res<BoxMaterialHandle>,
78 )>::new(world);
79 let (box_mesh_handle, box_material_handle) =
80 system_state.get_mut(world);
81
82 (box_mesh_handle.clone(), box_material_handle.clone())
83 };
84
85 world
86 .entity_mut(entity)
87 // Add our new `Mesh3d` and `MeshMaterial3d` to our tagged entity
88 .insert((
89 Mesh3d(box_mesh_handle),
90 MeshMaterial3d(box_material_handle),
91 transform,
92 ))
93 // Task is complete, so remove task component from entity
94 .remove::<ComputeTransform>();
95 });
96
97 command_queue
98 });
99
100 // Spawn new entity and add our new task as a component
101 commands.entity(entity).insert(ComputeTransform(task));
102 }
103 }
104 }
105}
Sourcepub fn inspect_entity(
&self,
entity: Entity,
) -> Result<impl Iterator<Item = &ComponentInfo>, EntityDoesNotExistError>
pub fn inspect_entity( &self, entity: Entity, ) -> Result<impl Iterator<Item = &ComponentInfo>, EntityDoesNotExistError>
Returns the components of an Entity
through ComponentInfo
.
Sourcepub fn get_entity<F>(
&self,
entities: F,
) -> Result<<F as WorldEntityFetch>::Ref<'_>, EntityDoesNotExistError>where
F: WorldEntityFetch,
pub fn get_entity<F>(
&self,
entities: F,
) -> Result<<F as WorldEntityFetch>::Ref<'_>, EntityDoesNotExistError>where
F: WorldEntityFetch,
Returns EntityRef
s that expose read-only operations for the given
entities
, returning Err
if any of the given entities do not exist.
Instead of immediately unwrapping the value returned from this function,
prefer World::entity
.
This function supports fetching a single entity or multiple entities:
- Pass an
Entity
to receive a singleEntityRef
. - Pass a slice of
Entity
s to receive aVec<EntityRef>
. - Pass an array of
Entity
s to receive an equally-sized array ofEntityRef
s. - Pass a reference to a
EntityHashSet
to receive anEntityHashMap<EntityRef>
.
§Errors
If any of the given entities
do not exist in the world, the first
Entity
found to be missing will return an EntityDoesNotExistError
.
§Examples
For examples, see World::entity
.
Sourcepub fn get_entity_mut<F>(
&mut self,
entities: F,
) -> Result<<F as WorldEntityFetch>::Mut<'_>, EntityMutableFetchError>where
F: WorldEntityFetch,
pub fn get_entity_mut<F>(
&mut self,
entities: F,
) -> Result<<F as WorldEntityFetch>::Mut<'_>, EntityMutableFetchError>where
F: WorldEntityFetch,
Returns EntityMut
s that expose read and write operations for the
given entities
, returning Err
if any of the given entities do not
exist. Instead of immediately unwrapping the value returned from this
function, prefer World::entity_mut
.
This function supports fetching a single entity or multiple entities:
- Pass an
Entity
to receive a singleEntityWorldMut
.- This reference type allows for structural changes to the entity, such as adding or removing components, or despawning the entity.
- Pass a slice of
Entity
s to receive aVec<EntityMut>
. - Pass an array of
Entity
s to receive an equally-sized array ofEntityMut
s. - Pass a reference to a
EntityHashSet
to receive anEntityHashMap<EntityMut>
.
In order to perform structural changes on the returned entity reference,
such as adding or removing components, or despawning the entity, only a
single Entity
can be passed to this function. Allowing multiple
entities at the same time with structural access would lead to undefined
behavior, so EntityMut
is returned when requesting multiple entities.
§Errors
- Returns
EntityMutableFetchError::EntityDoesNotExist
if any of the givenentities
do not exist in the world.- Only the first entity found to be missing will be returned.
- Returns
EntityMutableFetchError::AliasedMutability
if the same entity is requested multiple times.
§Examples
For examples, see World::entity_mut
.
Sourcepub fn iter_entities(&self) -> impl Iterator<Item = EntityRef<'_>>
pub fn iter_entities(&self) -> impl Iterator<Item = EntityRef<'_>>
Sourcepub fn iter_entities_mut(&mut self) -> impl Iterator<Item = EntityMut<'_>>
pub fn iter_entities_mut(&mut self) -> impl Iterator<Item = EntityMut<'_>>
Returns a mutable iterator over all entities in the World
.
Sourcepub fn entities_and_commands(&mut self) -> (EntityFetcher<'_>, Commands<'_, '_>)
pub fn entities_and_commands(&mut self) -> (EntityFetcher<'_>, Commands<'_, '_>)
Simultaneously provides access to entity data and a command queue, which will be applied when the world is next flushed.
This allows using borrowed entity data to construct commands where the borrow checker would otherwise prevent it.
See DeferredWorld::entities_and_commands
for the deferred version.
§Example
#[derive(Component)]
struct Targets(Vec<Entity>);
#[derive(Component)]
struct TargetedBy(Entity);
let mut world: World = // ...
let (entities, mut commands) = world.entities_and_commands();
let entity = entities.get(eid).unwrap();
for &target in entity.get::<Targets>().unwrap().0.iter() {
commands.entity(target).insert(TargetedBy(eid));
}
Sourcepub fn spawn_empty(&mut self) -> EntityWorldMut<'_>
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?
136fn demo_3(world: &mut World) {
137 // This is a list of dynamic components we will create.
138 // The first item is the name of the component, and the second is the size
139 // in bytes.
140 let my_dynamic_components = [("Foo", 1), ("Bar", 2), ("Baz", 4)];
141
142 // This pipeline takes our component descriptions, registers them, and gets
143 // their ComponentId's.
144 let my_registered_components = my_dynamic_components
145 .into_iter()
146 .map(|(name, size)| {
147 // SAFETY:
148 // - No drop command is required
149 // - The component will store [u8; size], which is Send + Sync
150 let descriptor = unsafe {
151 ComponentDescriptor::new_with_layout(
152 name.to_string(),
153 StorageType::Table,
154 Layout::array::<u8>(size).unwrap(),
155 None,
156 false,
157 ComponentCloneBehavior::Default,
158 )
159 };
160
161 (name, size, descriptor)
162 })
163 .map(|(name, size, descriptor)| {
164 let component_id = world.register_component_with_descriptor(descriptor);
165
166 (name, size, component_id)
167 })
168 .collect::<Vec<(&str, usize, ComponentId)>>();
169
170 // Now that our components are registered, let's add them to an entity
171 let mut entity = world.spawn_empty();
172
173 for (_name, size, component_id) in &my_registered_components {
174 // We're just storing some zeroes for the sake of demonstration.
175 let data = core::iter::repeat_n(0, *size).collect::<Vec<u8>>();
176
177 OwningPtr::make(data, |ptr| {
178 // SAFETY:
179 // - ComponentId has been taken from the same world
180 // - Array is created to the layout specified in the world
181 unsafe {
182 entity.insert_by_id(*component_id, ptr);
183 }
184 });
185 }
186
187 for (_name, _size, component_id) in &my_registered_components {
188 // With immutable components, we can read the values...
189 assert!(entity.get_by_id(*component_id).is_ok());
190
191 // ...but we cannot gain a mutable reference.
192 assert!(entity.get_mut_by_id(*component_id).is_err());
193
194 // Instead, you must either remove or replace the value.
195 }
196}
More examples
79fn stress_test(num_entities: u32, num_components: u32, num_systems: u32) {
80 let mut rng = ChaCha8Rng::seed_from_u64(42);
81 let mut app = App::default();
82 let world = app.world_mut();
83
84 // register a bunch of components
85 let component_ids: Vec<ComponentId> = (1..=num_components)
86 .map(|i| {
87 world.register_component_with_descriptor(
88 // SAFETY:
89 // * We don't implement a drop function
90 // * u8 is Sync and Send
91 unsafe {
92 ComponentDescriptor::new_with_layout(
93 format!("Component{}", i).to_string(),
94 StorageType::Table,
95 Layout::new::<u8>(),
96 None,
97 true, // is mutable
98 ComponentCloneBehavior::Default,
99 )
100 },
101 )
102 })
103 .collect();
104
105 // fill the schedule with systems
106 let mut schedule = Schedule::new(Update);
107 for _ in 1..=num_systems {
108 let num_access_components = rng.gen_range(1..10);
109 let access_components: Vec<ComponentId> = component_ids
110 .choose_multiple(&mut rng, num_access_components)
111 .copied()
112 .collect();
113 let system = (QueryParamBuilder::new(|builder| {
114 for &access_component in &access_components {
115 if rand::random::<bool>() {
116 builder.mut_id(access_component);
117 } else {
118 builder.ref_id(access_component);
119 }
120 }
121 }),)
122 .build_state(world)
123 .build_any_system(base_system);
124 schedule.add_systems((move || access_components.clone()).pipe(system));
125 }
126
127 // spawn a bunch of entities
128 for _ in 1..=num_entities {
129 let num_components = rng.gen_range(1..10);
130 let components: Vec<ComponentId> = component_ids
131 .choose_multiple(&mut rng, num_components)
132 .copied()
133 .collect();
134
135 let mut entity = world.spawn_empty();
136 // We use `ManuallyDrop` here as we need to avoid dropping the u8's when `values` is dropped
137 // since ownership of the values is passed to the world in `insert_by_ids`.
138 // But we do want to deallocate the memory when values is dropped.
139 let mut values: Vec<ManuallyDrop<u8>> = components
140 .iter()
141 .map(|_id| ManuallyDrop::new(rng.gen_range(0..255)))
142 .collect();
143 let ptrs: Vec<OwningPtr> = values
144 .iter_mut()
145 .map(|value| {
146 // SAFETY:
147 // * We don't read/write `values` binding after this and values are `ManuallyDrop`,
148 // so we have the right to drop/move the values
149 unsafe { PtrMut::from(value).promote() }
150 })
151 .collect();
152 // SAFETY:
153 // * component_id's are from the same world
154 // * `values` was initialized above, so references are valid
155 unsafe {
156 entity.insert_by_ids(&components, ptrs.into_iter());
157 }
158 }
159
160 println!(
161 "Number of Archetype-Components: {}",
162 world.archetypes().archetype_components_len()
163 );
164
165 // overwrite Update schedule in the app
166 app.add_schedule(schedule);
167 app.add_plugins(MinimalPlugins)
168 .add_plugins(DiagnosticsPlugin)
169 .add_plugins(LogPlugin::default())
170 .add_plugins(FrameTimeDiagnosticsPlugin::default())
171 .add_plugins(LogDiagnosticsPlugin::filtered(vec![DiagnosticPath::new(
172 "fps",
173 )]));
174 app.run();
175}
51fn main() {
52 let mut world = World::new();
53 let mut lines = std::io::stdin().lines();
54 let mut component_names = HashMap::<String, ComponentId>::new();
55 let mut component_info = HashMap::<ComponentId, ComponentInfo>::new();
56
57 println!("{PROMPT}");
58 loop {
59 print!("\n> ");
60 let _ = std::io::stdout().flush();
61 let Some(Ok(line)) = lines.next() else {
62 return;
63 };
64
65 if line.is_empty() {
66 return;
67 };
68
69 let Some((first, rest)) = line.trim().split_once(|c: char| c.is_whitespace()) else {
70 match &line.chars().next() {
71 Some('c') => println!("{COMPONENT_PROMPT}"),
72 Some('s') => println!("{ENTITY_PROMPT}"),
73 Some('q') => println!("{QUERY_PROMPT}"),
74 _ => println!("{PROMPT}"),
75 }
76 continue;
77 };
78
79 match &first[0..1] {
80 "c" => {
81 rest.split(',').for_each(|component| {
82 let mut component = component.split_whitespace();
83 let Some(name) = component.next() else {
84 return;
85 };
86 let size = match component.next().map(str::parse) {
87 Some(Ok(size)) => size,
88 _ => 0,
89 };
90 // Register our new component to the world with a layout specified by it's size
91 // SAFETY: [u64] is Send + Sync
92 let id = world.register_component_with_descriptor(unsafe {
93 ComponentDescriptor::new_with_layout(
94 name.to_string(),
95 StorageType::Table,
96 Layout::array::<u64>(size).unwrap(),
97 None,
98 true,
99 ComponentCloneBehavior::Default,
100 )
101 });
102 let Some(info) = world.components().get_info(id) else {
103 return;
104 };
105 component_names.insert(name.to_string(), id);
106 component_info.insert(id, info.clone());
107 println!("Component {} created with id: {}", name, id.index());
108 });
109 }
110 "s" => {
111 let mut to_insert_ids = Vec::new();
112 let mut to_insert_data = Vec::new();
113 rest.split(',').for_each(|component| {
114 let mut component = component.split_whitespace();
115 let Some(name) = component.next() else {
116 return;
117 };
118
119 // Get the id for the component with the given name
120 let Some(&id) = component_names.get(name) else {
121 println!("Component {name} does not exist");
122 return;
123 };
124
125 // Calculate the length for the array based on the layout created for this component id
126 let info = world.components().get_info(id).unwrap();
127 let len = info.layout().size() / size_of::<u64>();
128 let mut values: Vec<u64> = component
129 .take(len)
130 .filter_map(|value| value.parse::<u64>().ok())
131 .collect();
132 values.resize(len, 0);
133
134 // Collect the id and array to be inserted onto our entity
135 to_insert_ids.push(id);
136 to_insert_data.push(values);
137 });
138
139 let mut entity = world.spawn_empty();
140
141 // Construct an `OwningPtr` for each component in `to_insert_data`
142 let to_insert_ptr = to_owning_ptrs(&mut to_insert_data);
143
144 // SAFETY:
145 // - Component ids have been taken from the same world
146 // - Each array is created to the layout specified in the world
147 unsafe {
148 entity.insert_by_ids(&to_insert_ids, to_insert_ptr.into_iter());
149 }
150
151 println!("Entity spawned with id: {}", entity.id());
152 }
153 "q" => {
154 let mut builder = QueryBuilder::<FilteredEntityMut>::new(&mut world);
155 parse_query(rest, &mut builder, &component_names);
156 let mut query = builder.build();
157 query.iter_mut(&mut world).for_each(|filtered_entity| {
158 let terms = filtered_entity
159 .access()
160 .try_iter_component_access()
161 .unwrap()
162 .map(|component_access| {
163 let id = *component_access.index();
164 let ptr = filtered_entity.get_by_id(id).unwrap();
165 let info = component_info.get(&id).unwrap();
166 let len = info.layout().size() / size_of::<u64>();
167
168 // SAFETY:
169 // - All components are created with layout [u64]
170 // - len is calculated from the component descriptor
171 let data = unsafe {
172 std::slice::from_raw_parts_mut(
173 ptr.assert_unique().as_ptr().cast::<u64>(),
174 len,
175 )
176 };
177
178 // If we have write access, increment each value once
179 if matches!(component_access, ComponentAccessKind::Exclusive(_)) {
180 data.iter_mut().for_each(|data| {
181 *data += 1;
182 });
183 }
184
185 format!("{}: {:?}", info.name(), data[0..len].to_vec())
186 })
187 .collect::<Vec<_>>()
188 .join(", ");
189
190 println!("{}: {}", filtered_entity.id(), terms);
191 });
192 }
193 _ => continue,
194 }
195 }
196}
Sourcepub fn spawn<B>(&mut self, bundle: B) -> EntityWorldMut<'_>where
B: Bundle,
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. In case large batches of entities need to be spawned, consider using
World::spawn_batch
instead.
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?
More examples
244fn exclusive_player_system(world: &mut World) {
245 // this does the same thing as "new_player_system"
246 let total_players = world.resource_mut::<GameState>().total_players;
247 let should_add_player = {
248 let game_rules = world.resource::<GameRules>();
249 let add_new_player = random::<bool>();
250 add_new_player && total_players < game_rules.max_players
251 };
252 // Randomly add a new player
253 if should_add_player {
254 println!("Player {} has joined the game!", total_players + 1);
255 world.spawn((
256 Player {
257 name: format!("Player {}", total_players + 1),
258 },
259 Score { value: 0 },
260 PlayerStreak::None,
261 ));
262
263 let mut game_state = world.resource_mut::<GameState>();
264 game_state.total_players += 1;
265 }
266}
31fn demo_1(world: &mut World) {
32 // Immutable components can be inserted just like mutable components.
33 let mut entity = world.spawn((MyMutableComponent(false), MyImmutableComponent(false)));
34
35 // But where mutable components can be mutated...
36 let mut my_mutable_component = entity.get_mut::<MyMutableComponent>().unwrap();
37 my_mutable_component.0 = true;
38
39 // ...immutable ones cannot. The below fails to compile as `MyImmutableComponent`
40 // is declared as immutable.
41 // let mut my_immutable_component = entity.get_mut::<MyImmutableComponent>().unwrap();
42
43 // Instead, you could take or replace the immutable component to update its value.
44 let mut my_immutable_component = entity.take::<MyImmutableComponent>().unwrap();
45 my_immutable_component.0 = true;
46 entity.insert(my_immutable_component);
47}
48
49/// This is an example of a component like [`Name`](bevy::prelude::Name), but immutable.
50#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Component, Reflect)]
51#[reflect(Hash, Component)]
52#[component(
53 immutable,
54 // Since this component is immutable, we can fully capture all mutations through
55 // these component hooks. This allows for keeping other parts of the ECS synced
56 // to a component's value at all times.
57 on_insert = on_insert_name,
58 on_replace = on_replace_name,
59)]
60pub struct Name(pub &'static str);
61
62/// This index allows for O(1) lookups of an [`Entity`] by its [`Name`].
63#[derive(Resource, Default)]
64struct NameIndex {
65 name_to_entity: HashMap<Name, Entity>,
66}
67
68impl NameIndex {
69 fn get_entity(&self, name: &'static str) -> Option<Entity> {
70 self.name_to_entity.get(&Name(name)).copied()
71 }
72}
73
74/// When a [`Name`] is inserted, we will add it to our [`NameIndex`].
75///
76/// Since all mutations to [`Name`] are captured by hooks, we know it is not currently
77/// inserted in the index, and its value will not change without triggering a hook.
78fn on_insert_name(mut world: DeferredWorld<'_>, HookContext { entity, .. }: HookContext) {
79 let Some(&name) = world.entity(entity).get::<Name>() else {
80 unreachable!("OnInsert hook guarantees `Name` is available on entity")
81 };
82 let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
83 return;
84 };
85
86 index.name_to_entity.insert(name, entity);
87}
88
89/// When a [`Name`] is removed or replaced, remove it from our [`NameIndex`].
90///
91/// Since all mutations to [`Name`] are captured by hooks, we know it is currently
92/// inserted in the index.
93fn on_replace_name(mut world: DeferredWorld<'_>, HookContext { entity, .. }: HookContext) {
94 let Some(&name) = world.entity(entity).get::<Name>() else {
95 unreachable!("OnReplace hook guarantees `Name` is available on entity")
96 };
97 let Some(mut index) = world.get_resource_mut::<NameIndex>() else {
98 return;
99 };
100
101 index.name_to_entity.remove(&name);
102}
103
104fn demo_2(world: &mut World) {
105 // Setup our name index
106 world.init_resource::<NameIndex>();
107
108 // Spawn some entities!
109 let alyssa = world.spawn(Name("Alyssa")).id();
110 let javier = world.spawn(Name("Javier")).id();
111
112 // Check our index
113 let index = world.resource::<NameIndex>();
114
115 assert_eq!(index.get_entity("Alyssa"), Some(alyssa));
116 assert_eq!(index.get_entity("Javier"), Some(javier));
117
118 // Changing the name of an entity is also fully capture by our index
119 world.entity_mut(javier).insert(Name("Steven"));
120
121 // Javier changed their name to Steven
122 let steven = javier;
123
124 // Check our index
125 let index = world.resource::<NameIndex>();
126
127 assert_eq!(index.get_entity("Javier"), None);
128 assert_eq!(index.get_entity("Steven"), Some(steven));
129}
160fn save_scene_system(world: &mut World) {
161 // Scenes can be created from any ECS World.
162 // You can either create a new one for the scene or use the current World.
163 // For demonstration purposes, we'll create a new one.
164 let mut scene_world = World::new();
165
166 // The `TypeRegistry` resource contains information about all registered types (including components).
167 // This is used to construct scenes, so we'll want to ensure that our previous type registrations
168 // exist in this new scene world as well.
169 // To do this, we can simply clone the `AppTypeRegistry` resource.
170 let type_registry = world.resource::<AppTypeRegistry>().clone();
171 scene_world.insert_resource(type_registry);
172
173 let mut component_b = ComponentB::from_world(world);
174 component_b.value = "hello".to_string();
175 scene_world.spawn((
176 component_b,
177 ComponentA { x: 1.0, y: 2.0 },
178 Transform::IDENTITY,
179 Name::new("joe"),
180 ));
181 scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
182 scene_world.insert_resource(ResourceA { score: 1 });
183
184 // With our sample world ready to go, we can now create our scene using DynamicScene or DynamicSceneBuilder.
185 // For simplicity, we will create our scene using DynamicScene:
186 let scene = DynamicScene::from_world(&scene_world);
187
188 // Scenes can be serialized like this:
189 let type_registry = world.resource::<AppTypeRegistry>();
190 let type_registry = type_registry.read();
191 let serialized_scene = scene.serialize(&type_registry).unwrap();
192
193 // Showing the scene in the console
194 info!("{}", serialized_scene);
195
196 // Writing the scene to a new file. Using a task to avoid calling the filesystem APIs in a system
197 // as they are blocking.
198 //
199 // This can't work in Wasm as there is no filesystem access.
200 #[cfg(not(target_arch = "wasm32"))]
201 IoTaskPool::get()
202 .spawn(async move {
203 // Write the scene RON data to file
204 File::create(format!("assets/{NEW_SCENE_FILE_PATH}"))
205 .and_then(|mut file| file.write(serialized_scene.as_bytes()))
206 .expect("Error while writing scene to file");
207 })
208 .detach();
209}
Sourcepub fn spawn_batch<I>(
&mut self,
iter: I,
) -> SpawnBatchIter<'_, <I as IntoIterator>::IntoIter> ⓘwhere
I: IntoIterator,
<I as IntoIterator>::Item: Bundle,
<<I as IntoIterator>::Item as DynamicBundle>::Effect: NoBundleEffect,
pub fn spawn_batch<I>(
&mut self,
iter: I,
) -> SpawnBatchIter<'_, <I as IntoIterator>::IntoIter> ⓘwhere
I: IntoIterator,
<I as IntoIterator>::Item: Bundle,
<<I as IntoIterator>::Item as DynamicBundle>::Effect: NoBundleEffect,
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
using World::spawn
, 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);
Sourcepub fn get<T>(&self, entity: Entity) -> Option<&T>where
T: Component,
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?
60fn setup(world: &mut World) {
61 // In order to register component hooks the component must:
62 // - not be currently in use by any entities in the world
63 // - not already have a hook of that kind registered
64 // This is to prevent overriding hooks defined in plugins and other crates as well as keeping things fast
65 world
66 .register_component_hooks::<MyComponent>()
67 // There are 4 component lifecycle hooks: `on_add`, `on_insert`, `on_replace` and `on_remove`
68 // A hook has 2 arguments:
69 // - a `DeferredWorld`, this allows access to resource and component data as well as `Commands`
70 // - a `HookContext`, this provides access to the following contextual information:
71 // - the entity that triggered the hook
72 // - the component id of the triggering component, this is mostly used for dynamic components
73 // - the location of the code that caused the hook to trigger
74 //
75 // `on_add` will trigger when a component is inserted onto an entity without it
76 .on_add(
77 |mut world,
78 HookContext {
79 entity,
80 component_id,
81 caller,
82 ..
83 }| {
84 // You can access component data from within the hook
85 let value = world.get::<MyComponent>(entity).unwrap().0;
86 println!(
87 "{component_id:?} added to {entity} with value {value:?}{}",
88 caller
89 .map(|location| format!("due to {location}"))
90 .unwrap_or_default()
91 );
92 // Or access resources
93 world
94 .resource_mut::<MyComponentIndex>()
95 .insert(value, entity);
96 // Or send events
97 world.send_event(MyEvent);
98 },
99 )
100 // `on_insert` will trigger when a component is inserted onto an entity,
101 // regardless of whether or not it already had it and after `on_add` if it ran
102 .on_insert(|world, _| {
103 println!("Current Index: {:?}", world.resource::<MyComponentIndex>());
104 })
105 // `on_replace` will trigger when a component is inserted onto an entity that already had it,
106 // and runs before the value is replaced.
107 // Also triggers when a component is removed from an entity, and runs before `on_remove`
108 .on_replace(|mut world, context| {
109 let value = world.get::<MyComponent>(context.entity).unwrap().0;
110 world.resource_mut::<MyComponentIndex>().remove(&value);
111 })
112 // `on_remove` will trigger when a component is removed from an entity,
113 // since it runs before the component is removed you can still access the component data
114 .on_remove(
115 |mut world,
116 HookContext {
117 entity,
118 component_id,
119 caller,
120 ..
121 }| {
122 let value = world.get::<MyComponent>(entity).unwrap().0;
123 println!(
124 "{component_id:?} removed from {entity} with value {value:?}{}",
125 caller
126 .map(|location| format!("due to {location}"))
127 .unwrap_or_default()
128 );
129 // You can also issue commands through `.commands()`
130 world.commands().entity(entity).despawn();
131 },
132 );
133}
Sourcepub fn get_mut<T>(&mut self, entity: Entity) -> Option<Mut<'_, T>>
pub fn get_mut<T>(&mut self, entity: Entity) -> Option<Mut<'_, T>>
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;
Sourcepub fn modify_component<T, R>(
&mut self,
entity: Entity,
f: impl FnOnce(&mut T) -> R,
) -> Result<Option<R>, EntityMutableFetchError>where
T: Component,
pub fn modify_component<T, R>(
&mut self,
entity: Entity,
f: impl FnOnce(&mut T) -> R,
) -> Result<Option<R>, EntityMutableFetchError>where
T: Component,
Temporarily removes a Component
T
from the provided Entity
and
runs the provided closure on it, returning the result if T
was available.
This will trigger the OnRemove
and OnReplace
component hooks without
causing an archetype move.
This is most useful with immutable components, where removal and reinsertion is the only way to modify a value.
If you do not need to ensure the above hooks are triggered, and your component
is mutable, prefer using get_mut
.
§Examples
#[derive(Component, PartialEq, Eq, Debug)]
#[component(immutable)]
struct Foo(bool);
world.modify_component(entity, |foo: &mut Foo| {
foo.0 = true;
});
Sourcepub fn modify_component_by_id<R>(
&mut self,
entity: Entity,
component_id: ComponentId,
f: impl for<'a> FnOnce(MutUntyped<'a>) -> R,
) -> Result<Option<R>, EntityMutableFetchError>
pub fn modify_component_by_id<R>( &mut self, entity: Entity, component_id: ComponentId, f: impl for<'a> FnOnce(MutUntyped<'a>) -> R, ) -> Result<Option<R>, EntityMutableFetchError>
Temporarily removes a Component
identified by the provided
ComponentId
from the provided Entity
and runs the provided
closure on it, returning the result if the component was available.
This will trigger the OnRemove
and OnReplace
component hooks without
causing an archetype move.
This is most useful with immutable components, where removal and reinsertion is the only way to modify a value.
If you do not need to ensure the above hooks are triggered, and your component
is mutable, prefer using get_mut_by_id
.
You should prefer the typed modify_component
whenever possible.
Sourcepub fn despawn(&mut self, entity: Entity) -> bool
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 will also despawn the entities in any RelationshipTarget
that is configured
to despawn descendants. For example, this will recursively despawn Children
.
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_err());
assert!(world.get::<Position>(entity).is_none());
Sourcepub fn try_despawn(&mut self, entity: Entity) -> Result<(), EntityDespawnError>
pub fn try_despawn(&mut self, entity: Entity) -> Result<(), EntityDespawnError>
Despawns the given entity
, if it exists. This will also remove all of the entity’s
Components
.
Returns an EntityDespawnError
if the entity does not exist.
§Note
This will also despawn the entities in any RelationshipTarget
that is configured
to despawn descendants. For example, this will recursively despawn Children
.
Sourcepub fn clear_trackers(&mut self)
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 called automatically
by bevy_app::App::update
and bevy_app::SubApp::update
, so you don’t need to call it manually.
When using bevy_ecs
as a separate standalone crate however, you do 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());
Sourcepub fn query<D>(&mut self) -> QueryState<D>where
D: QueryData,
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")),
]);
Sourcepub fn query_filtered<D, F>(&mut self) -> QueryState<D, F>where
D: QueryData,
F: QueryFilter,
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]);
Sourcepub fn try_query<D>(&self) -> Option<QueryState<D>>where
D: QueryData,
pub fn try_query<D>(&self) -> Option<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,
}
let mut world = World::new();
world.spawn_batch(vec![
Position { x: 0.0, y: 0.0 },
Position { x: 1.0, y: 1.0 },
]);
fn get_positions(world: &World) -> Vec<(Entity, &Position)> {
let mut query = world.try_query::<(Entity, &Position)>().unwrap();
query.iter(world).collect()
}
let positions = get_positions(&world);
assert_eq!(world.get::<Position>(positions[0].0).unwrap(), positions[0].1);
assert_eq!(world.get::<Position>(positions[1].0).unwrap(), positions[1].1);
Requires only an immutable world reference, but may fail if, for example, the components that make up this query have not been registered into the world.
use bevy_ecs::{component::Component, entity::Entity, world::World};
#[derive(Component)]
struct A;
let mut world = World::new();
let none_query = world.try_query::<&A>();
assert!(none_query.is_none());
world.register_component::<A>();
let some_query = world.try_query::<&A>();
assert!(some_query.is_some());
Sourcepub fn try_query_filtered<D, F>(&self) -> Option<QueryState<D, F>>where
D: QueryData,
F: QueryFilter,
pub fn try_query_filtered<D, F>(&self) -> Option<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.try_query_filtered::<Entity, With<B>>().unwrap();
let matching_entities = query.iter(&world).collect::<Vec<Entity>>();
assert_eq!(matching_entities, vec![e2]);
Requires only an immutable world reference, but may fail if, for example, the components that make up this query have not been registered into the world.
Sourcepub fn removed<T>(&self) -> impl Iterator<Item = Entity>where
T: Component,
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
.
Sourcepub fn removed_with_id(
&self,
component_id: ComponentId,
) -> impl Iterator<Item = Entity>
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
.
Sourcepub fn register_resource_with_descriptor(
&mut self,
descriptor: ComponentDescriptor,
) -> ComponentId
pub fn register_resource_with_descriptor( &mut self, descriptor: ComponentDescriptor, ) -> ComponentId
Registers a new Resource
type and returns the ComponentId
created for it.
This enables the dynamic registration of new Resource
definitions at runtime for
advanced use cases.
§Note
Registering a Resource
does not insert it into World
. For insertion, you could use
World::insert_resource_by_id
.
Sourcepub fn init_resource<R>(&mut self) -> ComponentId
pub fn init_resource<R>(&mut self) -> ComponentId
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.
Examples found in repository?
104fn demo_2(world: &mut World) {
105 // Setup our name index
106 world.init_resource::<NameIndex>();
107
108 // Spawn some entities!
109 let alyssa = world.spawn(Name("Alyssa")).id();
110 let javier = world.spawn(Name("Javier")).id();
111
112 // Check our index
113 let index = world.resource::<NameIndex>();
114
115 assert_eq!(index.get_entity("Alyssa"), Some(alyssa));
116 assert_eq!(index.get_entity("Javier"), Some(javier));
117
118 // Changing the name of an entity is also fully capture by our index
119 world.entity_mut(javier).insert(Name("Steven"));
120
121 // Javier changed their name to Steven
122 let steven = javier;
123
124 // Check our index
125 let index = world.resource::<NameIndex>();
126
127 assert_eq!(index.get_entity("Javier"), None);
128 assert_eq!(index.get_entity("Steven"), Some(steven));
129}
Sourcepub fn insert_resource<R>(&mut self, value: R)where
R: Resource,
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?
160fn save_scene_system(world: &mut World) {
161 // Scenes can be created from any ECS World.
162 // You can either create a new one for the scene or use the current World.
163 // For demonstration purposes, we'll create a new one.
164 let mut scene_world = World::new();
165
166 // The `TypeRegistry` resource contains information about all registered types (including components).
167 // This is used to construct scenes, so we'll want to ensure that our previous type registrations
168 // exist in this new scene world as well.
169 // To do this, we can simply clone the `AppTypeRegistry` resource.
170 let type_registry = world.resource::<AppTypeRegistry>().clone();
171 scene_world.insert_resource(type_registry);
172
173 let mut component_b = ComponentB::from_world(world);
174 component_b.value = "hello".to_string();
175 scene_world.spawn((
176 component_b,
177 ComponentA { x: 1.0, y: 2.0 },
178 Transform::IDENTITY,
179 Name::new("joe"),
180 ));
181 scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
182 scene_world.insert_resource(ResourceA { score: 1 });
183
184 // With our sample world ready to go, we can now create our scene using DynamicScene or DynamicSceneBuilder.
185 // For simplicity, we will create our scene using DynamicScene:
186 let scene = DynamicScene::from_world(&scene_world);
187
188 // Scenes can be serialized like this:
189 let type_registry = world.resource::<AppTypeRegistry>();
190 let type_registry = type_registry.read();
191 let serialized_scene = scene.serialize(&type_registry).unwrap();
192
193 // Showing the scene in the console
194 info!("{}", serialized_scene);
195
196 // Writing the scene to a new file. Using a task to avoid calling the filesystem APIs in a system
197 // as they are blocking.
198 //
199 // This can't work in Wasm as there is no filesystem access.
200 #[cfg(not(target_arch = "wasm32"))]
201 IoTaskPool::get()
202 .spawn(async move {
203 // Write the scene RON data to file
204 File::create(format!("assets/{NEW_SCENE_FILE_PATH}"))
205 .and_then(|mut file| file.write(serialized_scene.as_bytes()))
206 .expect("Error while writing scene to file");
207 })
208 .detach();
209}
Sourcepub fn init_non_send_resource<R>(&mut self) -> ComponentIdwhere
R: 'static + FromWorld,
pub fn init_non_send_resource<R>(&mut self) -> ComponentIdwhere
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.
Sourcepub fn insert_non_send_resource<R>(&mut self, value: R)where
R: 'static,
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.
Sourcepub fn remove_resource<R>(&mut self) -> Option<R>where
R: Resource,
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
.
Sourcepub fn remove_non_send_resource<R>(&mut self) -> Option<R>where
R: 'static,
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.
Sourcepub fn contains_resource<R>(&self) -> boolwhere
R: Resource,
pub fn contains_resource<R>(&self) -> boolwhere
R: Resource,
Returns true
if a resource of type R
exists. Otherwise returns false
.
Sourcepub fn contains_resource_by_id(&self, component_id: ComponentId) -> bool
pub fn contains_resource_by_id(&self, component_id: ComponentId) -> bool
Returns true
if a resource with provided component_id
exists. Otherwise returns false
.
Sourcepub fn contains_non_send<R>(&self) -> boolwhere
R: 'static,
pub fn contains_non_send<R>(&self) -> boolwhere
R: 'static,
Returns true
if a resource of type R
exists. Otherwise returns false
.
Sourcepub fn contains_non_send_by_id(&self, component_id: ComponentId) -> bool
pub fn contains_non_send_by_id(&self, component_id: ComponentId) -> bool
Returns true
if a resource with provided component_id
exists. Otherwise returns false
.
Sourcepub fn is_resource_added<R>(&self) -> boolwhere
R: Resource,
pub fn is_resource_added<R>(&self) -> boolwhere
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.
Sourcepub fn is_resource_added_by_id(&self, component_id: ComponentId) -> bool
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.
Sourcepub fn is_resource_changed<R>(&self) -> boolwhere
R: Resource,
pub fn is_resource_changed<R>(&self) -> boolwhere
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.
Sourcepub fn is_resource_changed_by_id(&self, component_id: ComponentId) -> bool
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.
Sourcepub fn get_resource_change_ticks<R>(&self) -> Option<ComponentTicks>where
R: Resource,
pub fn get_resource_change_ticks<R>(&self) -> Option<ComponentTicks>where
R: Resource,
Retrieves the change ticks for the given resource.
Sourcepub fn get_resource_change_ticks_by_id(
&self,
component_id: ComponentId,
) -> Option<ComponentTicks>
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.
Sourcepub fn resource<R>(&self) -> &Rwhere
R: Resource,
pub fn resource<R>(&self) -> &Rwhere
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?
More examples
90 fn from_world(world: &mut World) -> Self {
91 let time = world.resource::<Time>();
92 ComponentB {
93 _time_since_startup: time.elapsed(),
94 value: "Default Value".to_string(),
95 }
96 }
97}
98
99/// A simple resource that also derives `Reflect`, allowing it to be stored in scenes.
100///
101/// Just like a component, you can skip serializing fields or implement `FromWorld` if needed.
102#[derive(Resource, Reflect, Default)]
103#[reflect(Resource)]
104struct ResourceA {
105 /// This resource tracks a `score` value.
106 pub score: u32,
107}
108
109/// # Scene File Paths
110///
111/// `SCENE_FILE_PATH` points to the original scene file that we'll be loading.
112/// `NEW_SCENE_FILE_PATH` points to the new scene file that we'll be creating
113/// (and demonstrating how to serialize to disk).
114///
115/// The initial scene file will be loaded below and not change when the scene is saved.
116const SCENE_FILE_PATH: &str = "scenes/load_scene_example.scn.ron";
117
118/// The new, updated scene data will be saved here so that you can see the changes.
119const NEW_SCENE_FILE_PATH: &str = "scenes/load_scene_example-new.scn.ron";
120
121/// Loads a scene from an asset file and spawns it in the current world.
122///
123/// Spawning a `DynamicSceneRoot` creates a new parent entity, which then spawns new
124/// instances of the scene's entities as its children. If you modify the
125/// `SCENE_FILE_PATH` scene file, or if you enable file watching, you can see
126/// changes reflected immediately.
127fn load_scene_system(mut commands: Commands, asset_server: Res<AssetServer>) {
128 commands.spawn(DynamicSceneRoot(asset_server.load(SCENE_FILE_PATH)));
129}
130
131/// Logs changes made to `ComponentA` entities, and also checks whether `ResourceA`
132/// has been recently added.
133///
134/// Any time a `ComponentA` is modified, that change will appear here. This system
135/// demonstrates how you might detect and handle scene updates at runtime.
136fn log_system(
137 query: Query<(Entity, &ComponentA), Changed<ComponentA>>,
138 res: Option<Res<ResourceA>>,
139) {
140 for (entity, component_a) in &query {
141 info!(" Entity({})", entity.index());
142 info!(
143 " ComponentA: {{ x: {} y: {} }}\n",
144 component_a.x, component_a.y
145 );
146 }
147 if let Some(res) = res {
148 if res.is_added() {
149 info!(" New ResourceA: {{ score: {} }}\n", res.score);
150 }
151 }
152}
153
154/// Demonstrates how to create a new scene from scratch, populate it with data,
155/// and then serialize it to a file. The new file is written to `NEW_SCENE_FILE_PATH`.
156///
157/// This system creates a fresh world, duplicates the type registry so that our
158/// custom component types are recognized, spawns some sample entities and resources,
159/// and then serializes the resulting dynamic scene.
160fn save_scene_system(world: &mut World) {
161 // Scenes can be created from any ECS World.
162 // You can either create a new one for the scene or use the current World.
163 // For demonstration purposes, we'll create a new one.
164 let mut scene_world = World::new();
165
166 // The `TypeRegistry` resource contains information about all registered types (including components).
167 // This is used to construct scenes, so we'll want to ensure that our previous type registrations
168 // exist in this new scene world as well.
169 // To do this, we can simply clone the `AppTypeRegistry` resource.
170 let type_registry = world.resource::<AppTypeRegistry>().clone();
171 scene_world.insert_resource(type_registry);
172
173 let mut component_b = ComponentB::from_world(world);
174 component_b.value = "hello".to_string();
175 scene_world.spawn((
176 component_b,
177 ComponentA { x: 1.0, y: 2.0 },
178 Transform::IDENTITY,
179 Name::new("joe"),
180 ));
181 scene_world.spawn(ComponentA { x: 3.0, y: 4.0 });
182 scene_world.insert_resource(ResourceA { score: 1 });
183
184 // With our sample world ready to go, we can now create our scene using DynamicScene or DynamicSceneBuilder.
185 // For simplicity, we will create our scene using DynamicScene:
186 let scene = DynamicScene::from_world(&scene_world);
187
188 // Scenes can be serialized like this:
189 let type_registry = world.resource::<AppTypeRegistry>();
190 let type_registry = type_registry.read();
191 let serialized_scene = scene.serialize(&type_registry).unwrap();
192
193 // Showing the scene in the console
194 info!("{}", serialized_scene);
195
196 // Writing the scene to a new file. Using a task to avoid calling the filesystem APIs in a system
197 // as they are blocking.
198 //
199 // This can't work in Wasm as there is no filesystem access.
200 #[cfg(not(target_arch = "wasm32"))]
201 IoTaskPool::get()
202 .spawn(async move {
203 // Write the scene RON data to file
204 File::create(format!("assets/{NEW_SCENE_FILE_PATH}"))
205 .and_then(|mut file| file.write(serialized_scene.as_bytes()))
206 .expect("Error while writing scene to file");
207 })
208 .detach();
209}
- examples/shader/custom_phase_item.rs
- examples/shader/texture_binding_array.rs
- examples/ecs/immutable_components.rs
- examples/ecs/ecs_guide.rs
- examples/3d/occlusion_culling.rs
- examples/shader/gpu_readback.rs
- examples/shader/compute_shader_game_of_life.rs
- examples/ecs/component_hooks.rs
- examples/shader/custom_post_processing.rs
Sourcepub fn resource_ref<R>(&self) -> Ref<'_, R>where
R: Resource,
pub fn resource_ref<R>(&self) -> Ref<'_, 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
.
Sourcepub fn resource_mut<R>(&mut self) -> Mut<'_, R>where
R: Resource,
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?
More examples
10fn my_runner(mut app: App) -> AppExit {
11 // Finalize plugin building, including running any necessary clean-up.
12 // This is normally completed by the default runner.
13 app.finish();
14 app.cleanup();
15
16 println!("Type stuff into the console");
17 for line in io::stdin().lines() {
18 {
19 let mut input = app.world_mut().resource_mut::<Input>();
20 input.0 = line.unwrap();
21 }
22 app.update();
23
24 if let Some(exit) = app.should_exit() {
25 return exit;
26 }
27 }
28
29 AppExit::Success
30}
46 fn finish(&self, app: &mut App) {
47 let render_app = app.sub_app_mut(RenderApp);
48 render_app.init_resource::<ComputePipeline>().add_systems(
49 Render,
50 prepare_bind_group
51 .in_set(RenderSet::PrepareBindGroups)
52 // We don't need to recreate the bind group every frame
53 .run_if(not(resource_exists::<GpuBufferBindGroup>)),
54 );
55
56 // Add the compute node as a top level node to the render graph
57 // This means it will only execute once per frame
58 render_app
59 .world_mut()
60 .resource_mut::<RenderGraph>()
61 .add_node(ComputeNodeLabel, ComputeNode::default());
62 }
101 fn build(&self, app: &mut App) {
102 // Extract the game of life image resource from the main world into the render world
103 // for operation on by the compute shader and display on the sprite.
104 app.add_plugins(ExtractResourcePlugin::<GameOfLifeImages>::default());
105 let render_app = app.sub_app_mut(RenderApp);
106 render_app.add_systems(
107 Render,
108 prepare_bind_group.in_set(RenderSet::PrepareBindGroups),
109 );
110
111 let mut render_graph = render_app.world_mut().resource_mut::<RenderGraph>();
112 render_graph.add_node(GameOfLifeLabel, GameOfLifeNode::default());
113 render_graph.add_node_edge(GameOfLifeLabel, bevy::render::graph::CameraDriverLabel);
114 }
244fn exclusive_player_system(world: &mut World) {
245 // this does the same thing as "new_player_system"
246 let total_players = world.resource_mut::<GameState>().total_players;
247 let should_add_player = {
248 let game_rules = world.resource::<GameRules>();
249 let add_new_player = random::<bool>();
250 add_new_player && total_players < game_rules.max_players
251 };
252 // Randomly add a new player
253 if should_add_player {
254 println!("Player {} has joined the game!", total_players + 1);
255 world.spawn((
256 Player {
257 name: format!("Player {}", total_players + 1),
258 },
259 Score { value: 0 },
260 PlayerStreak::None,
261 ));
262
263 let mut game_state = world.resource_mut::<GameState>();
264 game_state.total_players += 1;
265 }
266}
Sourcepub fn get_resource<R>(&self) -> Option<&R>where
R: Resource,
pub fn get_resource<R>(&self) -> Option<&R>where
R: Resource,
Gets a reference to the resource of the given type if it exists
Examples found in repository?
158fn failing_system(world: &mut World) -> Result {
159 world
160 // `get_resource` returns an `Option<T>`, so we use `ok_or` to convert it to a `Result` on
161 // which we can call `?` to propagate the error.
162 .get_resource::<UninitializedResource>()
163 // We can provide a `str` here because `BevyError` implements `From<&str>`.
164 .ok_or("Resource not initialized")?;
165
166 Ok(())
167}
168
169fn failing_commands(mut commands: Commands) {
170 commands
171 // This entity doesn't exist!
172 .entity(Entity::from_raw(12345678))
173 // Normally, this failed command would panic,
174 // but since we've set the global error handler to `warn`
175 // it will log a warning instead.
176 .insert(Transform::default());
177
178 // The error handlers for commands can be set individually as well,
179 // by using the queue_handled method.
180 commands.queue_handled(
181 |world: &mut World| -> Result {
182 world
183 .get_resource::<UninitializedResource>()
184 .ok_or("Resource not initialized when accessed in a command")?;
185
186 Ok(())
187 },
188 |error, context| {
189 error!("{error}, {context}");
190 },
191 );
192}
More examples
587 fn run<'w>(
588 &self,
589 graph: &mut RenderGraphContext,
590 render_context: &mut RenderContext<'w>,
591 (camera, view, target): QueryItem<'w, Self::ViewQuery>,
592 world: &'w World,
593 ) -> Result<(), NodeRunError> {
594 // First, we need to get our phases resource
595 let Some(stencil_phases) = world.get_resource::<ViewSortedRenderPhases<Stencil3d>>() else {
596 return Ok(());
597 };
598
599 // Get the view entity from the graph
600 let view_entity = graph.view_entity();
601
602 // Get the phase for the current view running our node
603 let Some(stencil_phase) = stencil_phases.get(&view.retained_view_entity) else {
604 return Ok(());
605 };
606
607 // Render pass setup
608 let mut render_pass = render_context.begin_tracked_render_pass(RenderPassDescriptor {
609 label: Some("stencil pass"),
610 // For the purpose of the example, we will write directly to the view target. A real
611 // stencil pass would write to a custom texture and that texture would be used in later
612 // passes to render custom effects using it.
613 color_attachments: &[Some(target.get_color_attachment())],
614 // We don't bind any depth buffer for this pass
615 depth_stencil_attachment: None,
616 timestamp_writes: None,
617 occlusion_query_set: None,
618 });
619
620 if let Some(viewport) = camera.viewport.as_ref() {
621 render_pass.set_camera_viewport(viewport);
622 }
623
624 // Render the phase
625 // This will execute each draw functions of each phase items queued in this phase
626 if let Err(err) = stencil_phase.render(&mut render_pass, world, view_entity) {
627 error!("Error encountered while rendering the stencil phase {err:?}");
628 }
629
630 Ok(())
631 }
340 fn run(
341 &self,
342 _graph: &mut RenderGraphContext,
343 render_context: &mut RenderContext,
344 world: &World,
345 ) -> Result<(), NodeRunError> {
346 let image_copiers = world.get_resource::<ImageCopiers>().unwrap();
347 let gpu_images = world
348 .get_resource::<RenderAssets<bevy::render::texture::GpuImage>>()
349 .unwrap();
350
351 for image_copier in image_copiers.iter() {
352 if !image_copier.enabled() {
353 continue;
354 }
355
356 let src_image = gpu_images.get(&image_copier.src_image).unwrap();
357
358 let mut encoder = render_context
359 .render_device()
360 .create_command_encoder(&CommandEncoderDescriptor::default());
361
362 let block_dimensions = src_image.texture_format.block_dimensions();
363 let block_size = src_image.texture_format.block_copy_size(None).unwrap();
364
365 // Calculating correct size of image row because
366 // copy_texture_to_buffer can copy image only by rows aligned wgpu::COPY_BYTES_PER_ROW_ALIGNMENT
367 // That's why image in buffer can be little bit wider
368 // This should be taken into account at copy from buffer stage
369 let padded_bytes_per_row = RenderDevice::align_copy_bytes_per_row(
370 (src_image.size.width as usize / block_dimensions.0 as usize) * block_size as usize,
371 );
372
373 encoder.copy_texture_to_buffer(
374 src_image.texture.as_image_copy(),
375 TexelCopyBufferInfo {
376 buffer: &image_copier.buffer,
377 layout: TexelCopyBufferLayout {
378 offset: 0,
379 bytes_per_row: Some(
380 std::num::NonZero::<u32>::new(padded_bytes_per_row as u32)
381 .unwrap()
382 .into(),
383 ),
384 rows_per_image: None,
385 },
386 },
387 src_image.size,
388 );
389
390 let render_queue = world.get_resource::<RenderQueue>().unwrap();
391 render_queue.submit(std::iter::once(encoder.finish()));
392 }
393
394 Ok(())
395 }
419 fn run<'w>(
420 &self,
421 _: &mut RenderGraphContext,
422 render_context: &mut RenderContext<'w>,
423 world: &'w World,
424 ) -> Result<(), NodeRunError> {
425 // Extract the buffers that hold the GPU indirect draw parameters from
426 // the world resources. We're going to read those buffers to determine
427 // how many meshes were actually drawn.
428 let (Some(indirect_parameters_buffers), Some(indirect_parameters_mapping_buffers)) = (
429 world.get_resource::<IndirectParametersBuffers>(),
430 world.get_resource::<IndirectParametersStagingBuffers>(),
431 ) else {
432 return Ok(());
433 };
434
435 // Get the indirect parameters buffers corresponding to the opaque 3D
436 // phase, since all our meshes are in that phase.
437 let Some(phase_indirect_parameters_buffers) =
438 indirect_parameters_buffers.get(&TypeId::of::<Opaque3d>())
439 else {
440 return Ok(());
441 };
442
443 // Grab both the buffers we're copying from and the staging buffers
444 // we're copying to. Remember that we can't map the indirect parameters
445 // buffers directly, so we have to copy their contents to a staging
446 // buffer.
447 let (
448 Some(indexed_data_buffer),
449 Some(indexed_batch_sets_buffer),
450 Some(indirect_parameters_staging_data_buffer),
451 Some(indirect_parameters_staging_batch_sets_buffer),
452 ) = (
453 phase_indirect_parameters_buffers.indexed.data_buffer(),
454 phase_indirect_parameters_buffers
455 .indexed
456 .batch_sets_buffer(),
457 indirect_parameters_mapping_buffers.data.as_ref(),
458 indirect_parameters_mapping_buffers.batch_sets.as_ref(),
459 )
460 else {
461 return Ok(());
462 };
463
464 // Copy from the indirect parameters buffers to the staging buffers.
465 render_context.command_encoder().copy_buffer_to_buffer(
466 indexed_data_buffer,
467 0,
468 indirect_parameters_staging_data_buffer,
469 0,
470 indexed_data_buffer.size(),
471 );
472 render_context.command_encoder().copy_buffer_to_buffer(
473 indexed_batch_sets_buffer,
474 0,
475 indirect_parameters_staging_batch_sets_buffer,
476 0,
477 indexed_batch_sets_buffer.size(),
478 );
479
480 Ok(())
481 }
Sourcepub fn get_resource_ref<R>(&self) -> Option<Ref<'_, R>>where
R: Resource,
pub fn get_resource_ref<R>(&self) -> Option<Ref<'_, R>>where
R: Resource,
Gets a reference including change detection to the resource of the given type if it exists.
Sourcepub fn get_resource_mut<R>(&mut self) -> Option<Mut<'_, R>>where
R: Resource,
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
Sourcepub fn get_resource_or_insert_with<R>(
&mut self,
func: impl FnOnce() -> R,
) -> Mut<'_, R>where
R: Resource,
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
.
§Example
#[derive(Resource)]
struct MyResource(i32);
let my_res = world.get_resource_or_insert_with(|| MyResource(10));
assert_eq!(my_res.0, 10);
Sourcepub fn get_resource_or_init<R>(&mut self) -> Mut<'_, R>
pub fn get_resource_or_init<R>(&mut self) -> Mut<'_, R>
Gets a mutable reference to the resource of type T
if it exists,
otherwise initializes the resource by calling its FromWorld
implementation.
§Example
#[derive(Resource)]
struct Foo(i32);
impl Default for Foo {
fn default() -> Self {
Self(15)
}
}
#[derive(Resource)]
struct MyResource(i32);
impl FromWorld for MyResource {
fn from_world(world: &mut World) -> Self {
let foo = world.get_resource_or_init::<Foo>();
Self(foo.0 * 2)
}
}
let my_res = world.get_resource_or_init::<MyResource>();
assert_eq!(my_res.0, 30);
Sourcepub fn non_send_resource<R>(&self) -> &Rwhere
R: 'static,
pub fn non_send_resource<R>(&self) -> &Rwhere
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.
Sourcepub fn non_send_resource_mut<R>(&mut self) -> Mut<'_, R>where
R: 'static,
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.
Sourcepub fn get_non_send_resource<R>(&self) -> Option<&R>where
R: 'static,
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.
Sourcepub fn get_non_send_resource_mut<R>(&mut self) -> Option<Mut<'_, R>>where
R: 'static,
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.
Sourcepub 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,
<B as DynamicBundle>::Effect: NoBundleEffect,
👎Deprecated since 0.16.0: This can cause extreme performance problems when used with lots of arbitrary free entities. See #18054 on GitHub.
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,
<B as DynamicBundle>::Effect: NoBundleEffect,
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)));
Sourcepub fn insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn insert_batch<I, B>(&mut self, batch: I)where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
For a given batch of (Entity
, Bundle
) pairs,
adds the Bundle
of components to each Entity
.
This is faster than doing equivalent operations one-by-one.
A batch can be any type that implements IntoIterator
containing (Entity, Bundle)
tuples,
such as a [Vec<(Entity, Bundle)>
] or an array [(Entity, Bundle); N]
.
This will overwrite any previous values of components shared by the Bundle
.
See World::insert_batch_if_new
to keep the old values instead.
§Panics
This function will panic if any of the associated entities do not exist.
For the fallible version, see World::try_insert_batch
.
Sourcepub fn insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn insert_batch_if_new<I, B>(&mut self, batch: I)where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
For a given batch of (Entity
, Bundle
) pairs,
adds the Bundle
of components to each Entity
without overwriting.
This is faster than doing equivalent operations one-by-one.
A batch can be any type that implements IntoIterator
containing (Entity, Bundle)
tuples,
such as a [Vec<(Entity, Bundle)>
] or an array [(Entity, Bundle); N]
.
This is the same as World::insert_batch
, but in case of duplicate
components it will leave the old values instead of replacing them with new ones.
§Panics
This function will panic if any of the associated entities do not exist.
For the fallible version, see World::try_insert_batch_if_new
.
Sourcepub fn try_insert_batch<I, B>(
&mut self,
batch: I,
) -> Result<(), TryInsertBatchError>where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn try_insert_batch<I, B>(
&mut self,
batch: I,
) -> Result<(), TryInsertBatchError>where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
For a given batch of (Entity
, Bundle
) pairs,
adds the Bundle
of components to each Entity
.
This is faster than doing equivalent operations one-by-one.
A batch can be any type that implements IntoIterator
containing (Entity, Bundle)
tuples,
such as a [Vec<(Entity, Bundle)>
] or an array [(Entity, Bundle); N]
.
This will overwrite any previous values of components shared by the Bundle
.
See World::try_insert_batch_if_new
to keep the old values instead.
Returns a TryInsertBatchError
if any of the provided entities do not exist.
For the panicking version, see World::insert_batch
.
Sourcepub fn try_insert_batch_if_new<I, B>(
&mut self,
batch: I,
) -> Result<(), TryInsertBatchError>where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
pub fn try_insert_batch_if_new<I, B>(
&mut self,
batch: I,
) -> Result<(), TryInsertBatchError>where
I: IntoIterator,
<I as IntoIterator>::IntoIter: Iterator<Item = (Entity, B)>,
B: Bundle,
<B as DynamicBundle>::Effect: NoBundleEffect,
For a given batch of (Entity
, Bundle
) pairs,
adds the Bundle
of components to each Entity
without overwriting.
This is faster than doing equivalent operations one-by-one.
A batch can be any type that implements IntoIterator
containing (Entity, Bundle)
tuples,
such as a [Vec<(Entity, Bundle)>
] or an array [(Entity, Bundle); N]
.
This is the same as World::try_insert_batch
, but in case of duplicate
components it will leave the old values instead of replacing them with new ones.
Returns a TryInsertBatchError
if any of the provided entities do not exist.
For the panicking version, see World::insert_batch_if_new
.
Sourcepub fn resource_scope<R, U>(
&mut self,
f: impl FnOnce(&mut World, Mut<'_, R>) -> U,
) -> Uwhere
R: Resource,
pub fn resource_scope<R, U>(
&mut self,
f: impl FnOnce(&mut World, Mut<'_, R>) -> U,
) -> Uwhere
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);
See also try_resource_scope
.
Sourcepub fn try_resource_scope<R, U>(
&mut self,
f: impl FnOnce(&mut World, Mut<'_, R>) -> U,
) -> Option<U>where
R: Resource,
pub fn try_resource_scope<R, U>(
&mut self,
f: impl FnOnce(&mut World, Mut<'_, R>) -> U,
) -> Option<U>where
R: Resource,
Temporarily removes the requested resource from this World
if it exists, runs custom user code,
then re-adds the resource before returning. Returns None
if the resource does not exist in this World
.
This enables safe simultaneous mutable access to both a resource and the rest of the World
.
For more complex access patterns, consider using SystemState
.
See also resource_scope
.
Sourcepub fn send_event<E>(&mut self, event: E) -> Option<EventId<E>>where
E: Event,
pub fn send_event<E>(&mut self, event: E) -> Option<EventId<E>>where
E: Event,
Sourcepub fn send_event_default<E>(&mut self) -> Option<EventId<E>>
pub fn send_event_default<E>(&mut self) -> Option<EventId<E>>
Sourcepub fn send_event_batch<E>(
&mut self,
events: impl IntoIterator<Item = E>,
) -> Option<SendBatchIds<E>>where
E: Event,
pub fn send_event_batch<E>(
&mut self,
events: impl IntoIterator<Item = E>,
) -> Option<SendBatchIds<E>>where
E: Event,
Sourcepub unsafe fn insert_resource_by_id(
&mut self,
component_id: ComponentId,
value: OwningPtr<'_>,
caller: MaybeLocation,
)
pub unsafe fn insert_resource_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_>, caller: MaybeLocation, )
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.
Sourcepub unsafe fn insert_non_send_by_id(
&mut self,
component_id: ComponentId,
value: OwningPtr<'_>,
caller: MaybeLocation,
)
pub unsafe fn insert_non_send_by_id( &mut self, component_id: ComponentId, value: OwningPtr<'_>, caller: MaybeLocation, )
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.
Sourcepub fn flush(&mut self)
pub fn flush(&mut self)
Flushes queued entities and commands.
Queued entities will be spawned, and then commands will be applied.
Sourcepub fn increment_change_tick(&mut self) -> Tick
pub fn increment_change_tick(&mut self) -> Tick
Increments the world’s current change tick and returns the old value.
If you need to call this method, but do not have &mut
access to the world,
consider using as_unsafe_world_cell_readonly
to obtain an UnsafeWorldCell
and calling increment_change_tick
on that.
Note that this can be done in safe code, despite the name of the type.
Sourcepub fn read_change_tick(&self) -> Tick
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.
Sourcepub fn change_tick(&mut self) -> Tick
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.
Sourcepub fn last_change_tick(&self) -> Tick
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.
Sourcepub fn last_change_tick_scope<T>(
&mut self,
last_change_tick: Tick,
f: impl FnOnce(&mut World) -> T,
) -> T
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;
}
}
}
Sourcepub fn check_change_ticks(&mut self)
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.
Sourcepub fn clear_all(&mut self)
pub fn clear_all(&mut self)
Runs both clear_entities
and clear_resources
,
invalidating all Entity
and resource fetches such as Res
, ResMut
Sourcepub fn clear_entities(&mut self)
pub fn clear_entities(&mut self)
Despawns all entities in this World
.
Sourcepub fn clear_resources(&mut self)
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.
Sourcepub fn register_bundle<B>(&mut self) -> &BundleInfowhere
B: Bundle,
pub fn register_bundle<B>(&mut self) -> &BundleInfowhere
B: Bundle,
Registers all of the components in the given Bundle
and returns both the component
ids and the bundle id.
This is largely equivalent to calling register_component
on each
component in the bundle.
Sourcepub fn register_dynamic_bundle(
&mut self,
component_ids: &[ComponentId],
) -> &BundleInfo
pub fn register_dynamic_bundle( &mut self, component_ids: &[ComponentId], ) -> &BundleInfo
Registers the given ComponentId
s as a dynamic bundle and returns both the required component ids and the bundle id.
Note that the components need to be registered first, this function only creates a bundle combining them. Components
can be registered with World::register_component
/_with_descriptor
.
You should prefer to use the typed API World::register_bundle
where possible and only use this in cases where
not all of the actual types are known at compile time.
§Panics
This function will panic if any of the provided component ids do not belong to a component known to this World
.
Source§impl World
impl World
Sourcepub fn get_resource_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>>
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.
Sourcepub fn get_resource_mut_by_id(
&mut self,
component_id: ComponentId,
) -> Option<MutUntyped<'_>>
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.
Sourcepub fn iter_resources(&self) -> impl Iterator<Item = (&ComponentInfo, Ptr<'_>)>
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 TypeId
s
// 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::default();
// 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);
}
Sourcepub fn iter_resources_mut(
&mut self,
) -> impl Iterator<Item = (&ComponentInfo, MutUntyped<'_>)>
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::default();
// 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);
}
Sourcepub fn get_non_send_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>>
pub fn get_non_send_by_id(&self, component_id: ComponentId) -> Option<Ptr<'_>>
Gets a !Send
resource to the resource with the id ComponentId
if it exists.
The returned pointer must not be used to modify the resource, and must not be
dereferenced after the immutable borrow of the World
ends.
You should prefer to use the typed API World::get_resource
where possible and only
use this in cases where the actual types are not known at compile time.
§Panics
This function will panic if it isn’t called from the same thread that the resource was inserted from.
Sourcepub fn get_non_send_mut_by_id(
&mut self,
component_id: ComponentId,
) -> Option<MutUntyped<'_>>
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.
Sourcepub fn remove_resource_by_id(&mut self, component_id: ComponentId) -> Option<()>
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.
Sourcepub fn remove_non_send_by_id(&mut self, component_id: ComponentId) -> Option<()>
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.
Sourcepub fn get_by_id(
&self,
entity: Entity,
component_id: ComponentId,
) -> Option<Ptr<'_>>
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.
Sourcepub fn get_mut_by_id(
&mut self,
entity: Entity,
component_id: ComponentId,
) -> Option<MutUntyped<'_>>
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.
Source§impl World
impl World
Sourcepub fn add_schedule(&mut self, schedule: Schedule)
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.
Sourcepub fn try_schedule_scope<R>(
&mut self,
label: impl ScheduleLabel,
f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> Result<R, TryRunScheduleError>
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
.
Sourcepub fn schedule_scope<R>(
&mut self,
label: impl ScheduleLabel,
f: impl FnOnce(&mut World, &mut Schedule) -> R,
) -> R
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.
Sourcepub fn try_run_schedule(
&mut self,
label: impl ScheduleLabel,
) -> Result<(), TryRunScheduleError>
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.
Examples found in repository?
95 fn run_reenter<S: States>(transition: In<Option<StateTransitionEvent<S>>>, world: &mut World) {
96 // We return early if no transition event happened.
97 let Some(transition) = transition.0 else {
98 return;
99 };
100
101 // If we wanted to ignore identity transitions,
102 // we'd compare `exited` and `entered` here,
103 // and return if they were the same.
104
105 // We check if we actually entered a state.
106 // A [`None`] would indicate that the state was removed from the world.
107 // This only happens in the case of [`SubStates`] and [`ComputedStates`].
108 let Some(entered) = transition.entered else {
109 return;
110 };
111
112 // If all conditions are valid, we run our custom schedule.
113 let _ = world.try_run_schedule(OnReenter(entered));
114
115 // If you want to overwrite the default `OnEnter` behavior to act like re-enter,
116 // you can do so by running the `OnEnter` schedule here. Note that you don't want
117 // to run `OnEnter` when the default behavior does so.
118 // ```
119 // if transition.entered != transition.exited {
120 // return;
121 // }
122 // let _ = world.try_run_schedule(OnReenter(entered));
123 // ```
124 }
125
126 /// Custom schedule that will behave like [`OnExit`], but run on identity transitions.
127 #[derive(ScheduleLabel, Clone, Debug, PartialEq, Eq, Hash)]
128 pub struct OnReexit<S: States>(pub S);
129
130 fn run_reexit<S: States>(transition: In<Option<StateTransitionEvent<S>>>, world: &mut World) {
131 let Some(transition) = transition.0 else {
132 return;
133 };
134 let Some(exited) = transition.exited else {
135 return;
136 };
137
138 let _ = world.try_run_schedule(OnReexit(exited));
139 }
Sourcepub fn run_schedule(&mut self, label: impl ScheduleLabel)
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.
Sourcepub fn allow_ambiguous_component<T>(&mut self)where
T: Component,
pub fn allow_ambiguous_component<T>(&mut self)where
T: Component,
Ignore system order ambiguities caused by conflicts on Component
s of type T
.
Sourcepub fn allow_ambiguous_resource<T>(&mut self)where
T: Resource,
pub fn allow_ambiguous_resource<T>(&mut self)where
T: Resource,
Ignore system order ambiguities caused by conflicts on Resource
s of type T
.
Trait Implementations§
Source§impl DirectAssetAccessExt for World
impl DirectAssetAccessExt for World
Source§fn add_asset<'a, A>(&mut self, asset: impl Into<A>) -> Handle<A>where
A: Asset,
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.
Source§fn load_asset<'a, A>(&self, path: impl Into<AssetPath<'a>>) -> Handle<A>where
A: Asset,
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.
Source§fn load_asset_with_settings<'a, A, S>(
&self,
path: impl Into<AssetPath<'a>>,
settings: impl Fn(&mut S) + Send + Sync + 'static,
) -> Handle<A>
fn load_asset_with_settings<'a, A, S>( &self, path: impl Into<AssetPath<'a>>, settings: impl Fn(&mut S) + Send + Sync + 'static, ) -> Handle<A>
Load an asset with settings, similarly to AssetServer::load_with_settings
.
§Panics
If self
doesn’t have an AssetServer
resource initialized yet.
Source§impl<'w> From<&'w World> for FilteredResources<'w, 'static>
impl<'w> From<&'w World> for FilteredResources<'w, 'static>
Source§fn from(value: &'w World) -> FilteredResources<'w, 'static>
fn from(value: &'w World) -> FilteredResources<'w, 'static>
Source§impl<'w> From<&'w World> for UnsafeWorldCell<'w>
impl<'w> From<&'w World> for UnsafeWorldCell<'w>
Source§fn from(value: &'w World) -> UnsafeWorldCell<'w>
fn from(value: &'w World) -> UnsafeWorldCell<'w>
Source§impl<'w> From<&'w mut World> for DeferredWorld<'w>
impl<'w> From<&'w mut World> for DeferredWorld<'w>
Source§fn from(world: &'w mut World) -> DeferredWorld<'w>
fn from(world: &'w mut World) -> DeferredWorld<'w>
Source§impl<'w> From<&'w mut World> for FilteredResources<'w, 'static>
impl<'w> From<&'w mut World> for FilteredResources<'w, 'static>
Source§fn from(value: &'w mut World) -> FilteredResources<'w, 'static>
fn from(value: &'w mut World) -> FilteredResources<'w, 'static>
Source§impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static>
impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static>
Source§fn from(value: &'w mut World) -> FilteredResourcesMut<'w, 'static>
fn from(value: &'w mut World) -> FilteredResourcesMut<'w, 'static>
Source§impl<'w> From<&'w mut World> for UnsafeWorldCell<'w>
impl<'w> From<&'w mut World> for UnsafeWorldCell<'w>
Source§fn from(value: &'w mut World) -> UnsafeWorldCell<'w>
fn from(value: &'w mut World) -> UnsafeWorldCell<'w>
Source§impl IsFocused for World
impl IsFocused for World
Source§fn is_focused(&self, entity: Entity) -> bool
fn is_focused(&self, entity: Entity) -> bool
Source§fn is_focus_within(&self, entity: Entity) -> bool
fn is_focus_within(&self, entity: Entity) -> bool
Source§fn is_focus_visible(&self, entity: Entity) -> bool
fn is_focus_visible(&self, entity: Entity) -> bool
Source§fn is_focus_within_visible(&self, entity: Entity) -> bool
fn is_focus_within_visible(&self, entity: Entity) -> bool
Source§impl RunSystemOnce for &mut World
impl RunSystemOnce for &mut World
Source§fn run_system_once_with<T, In, Out, Marker>(
self,
system: T,
input: <<<T as IntoSystem<In, Out, Marker>>::System as System>::In as SystemInput>::Inner<'_>,
) -> Result<Out, RunSystemError>where
T: IntoSystem<In, Out, Marker>,
In: SystemInput,
fn run_system_once_with<T, In, Out, Marker>(
self,
system: T,
input: <<<T as IntoSystem<In, Out, Marker>>::System as System>::In as SystemInput>::Inner<'_>,
) -> Result<Out, RunSystemError>where
T: IntoSystem<In, Out, Marker>,
In: SystemInput,
Source§fn run_system_once<T, Out, Marker>(
self,
system: T,
) -> Result<Out, RunSystemError>where
T: IntoSystem<(), Out, Marker>,
fn run_system_once<T, Out, Marker>(
self,
system: T,
) -> Result<Out, RunSystemError>where
T: IntoSystem<(), Out, Marker>,
Source§impl SystemParam for &World
impl SystemParam for &World
Source§type Item<'w, 's> = &'w World
type Item<'w, 's> = &'w World
Self
, instantiated with new lifetimes. Read moreSource§fn init_state(
_world: &mut World,
system_meta: &mut SystemMeta,
) -> <&World as SystemParam>::State
fn init_state( _world: &mut World, system_meta: &mut SystemMeta, ) -> <&World as SystemParam>::State
World
access used by this SystemParam
and creates a new instance of this param’s State
.Source§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>
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>
SystemParamFunction
. Read moreSource§unsafe fn new_archetype(
state: &mut Self::State,
archetype: &Archetype,
system_meta: &mut SystemMeta,
)
unsafe fn new_archetype( state: &mut Self::State, archetype: &Archetype, system_meta: &mut SystemMeta, )
Archetype
, registers the components accessed by this SystemParam
(if applicable).a Read moreSource§fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
fn apply(state: &mut Self::State, system_meta: &SystemMeta, world: &mut World)
SystemParam
’s state.
This is used to apply Commands
during ApplyDeferred
.Source§fn queue(
state: &mut Self::State,
system_meta: &SystemMeta,
world: DeferredWorld<'_>,
)
fn queue( state: &mut Self::State, system_meta: &SystemMeta, world: DeferredWorld<'_>, )
ApplyDeferred
.Source§unsafe fn validate_param(
state: &Self::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'_>,
) -> Result<(), SystemParamValidationError>
unsafe fn validate_param( state: &Self::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'_>, ) -> Result<(), SystemParamValidationError>
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, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self
using default()
.
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.