Struct oxygengine_core::ecs::World
source · pub struct World { /* private fields */ }
Expand description
An unordered collection of entities, each having any number of distinctly typed components
Similar to HashMap<Entity, Vec<Box<dyn Any>>>
where each Vec
never contains two of the same
type, but far more efficient to traverse.
The components of entities who have the same set of component types are stored in contiguous runs, allowing for extremely fast, cache-friendly iteration.
There is a maximum number of unique entity IDs, which means that there is a maximum number of live
entities. When old entities are despawned, their IDs will be reused on a future entity, and
old Entity
values with that ID will be invalidated.
Collisions
If an entity is despawned and its Entity
handle is preserved over the course of billions of
following spawns and despawns, that handle may, in rare circumstances, collide with a
newly-allocated Entity
handle. Very long-lived applications should therefore limit the period
over which they may retain handles of despawned entities.
Implementations§
source§impl World
impl World
sourcepub fn spawn(&mut self, components: impl DynamicBundle) -> Entity
pub fn spawn(&mut self, components: impl DynamicBundle) -> Entity
Create an entity with certain components
Returns the ID of the newly created entity.
Arguments can be tuples, structs annotated with #[derive(Bundle)]
, or the
result of calling build
on an
EntityBuilder
, which is useful if the set of components isn’t
statically known. To spawn an entity with only one component, use a one-element tuple like
(x,)
.
Any type that satisfies Send + Sync + 'static
can be used as a component.
Example
let mut world = World::new();
let a = world.spawn((123, "abc"));
let b = world.spawn((456, true));
sourcepub fn spawn_at(&mut self, handle: Entity, components: impl DynamicBundle)
pub fn spawn_at(&mut self, handle: Entity, components: impl DynamicBundle)
Create an entity with certain components and a specific Entity
handle.
See spawn
.
Despawns any existing entity with the same Entity::id
.
Useful for easy handle-preserving deserialization. Be cautious resurrecting old Entity
handles in already-populated worlds as it vastly increases the likelihood of collisions.
Example
let mut world = World::new();
let a = world.spawn((123, "abc"));
let b = world.spawn((456, true));
world.despawn(a);
assert!(!world.contains(a));
// all previous Entity values pointing to 'a' will be live again, instead pointing to the new entity.
world.spawn_at(a, (789, "ABC"));
assert!(world.contains(a));
sourcepub fn spawn_batch<I>(
&mut self,
iter: I
) -> SpawnBatchIter<'_, <I as IntoIterator>::IntoIter> ⓘwhere
I: IntoIterator,
<I as IntoIterator>::Item: Bundle + 'static,
pub fn spawn_batch<I>( &mut self, iter: I ) -> SpawnBatchIter<'_, <I as IntoIterator>::IntoIter> ⓘwhere I: IntoIterator, <I as IntoIterator>::Item: Bundle + 'static,
Efficiently spawn a large number of entities with the same statically-typed components
Faster than calling spawn
repeatedly with the same components, but requires
that component types are known at compile time.
Example
let mut world = World::new();
let entities = world.spawn_batch((0..1_000).map(|i| (i, "abc"))).collect::<Vec<_>>();
for i in 0..1_000 {
assert_eq!(*world.get::<&i32>(entities[i]).unwrap(), i as i32);
}
sourcepub fn spawn_column_batch(
&mut self,
batch: ColumnBatch
) -> SpawnColumnBatchIter<'_> ⓘ
pub fn spawn_column_batch( &mut self, batch: ColumnBatch ) -> SpawnColumnBatchIter<'_> ⓘ
Super-efficiently spawn the contents of a ColumnBatch
The fastest, but most specialized, way to spawn large numbers of entities. Useful for high performance deserialization. Supports dynamic component types.
sourcepub fn spawn_column_batch_at(&mut self, handles: &[Entity], batch: ColumnBatch)
pub fn spawn_column_batch_at(&mut self, handles: &[Entity], batch: ColumnBatch)
Hybrid of spawn_column_batch
and spawn_at
sourcepub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator<'_>
pub fn reserve_entities(&self, count: u32) -> ReserveEntitiesIterator<'_>
Allocate many entities ID concurrently
Unlike spawn
, this can be called concurrently with other operations on the
World
such as queries, but does not immediately create the entities. Reserved entities
are not visible to queries or world iteration, but can be otherwise operated on
freely. Operations that add or remove components or entities, such as insert
or despawn
,
will cause all outstanding reserved entities to become real entities before proceeding. This
can also be done explicitly by calling flush
.
Useful for reserving an ID that will later have components attached to it with insert
.
sourcepub fn reserve_entity(&self) -> Entity
pub fn reserve_entity(&self) -> Entity
Allocate an entity ID concurrently
See reserve_entities
.
sourcepub fn despawn(&mut self, entity: Entity) -> Result<(), NoSuchEntity>
pub fn despawn(&mut self, entity: Entity) -> Result<(), NoSuchEntity>
Destroy an entity and all its components
See also take
.
sourcepub fn reserve<T>(&mut self, additional: u32)where
T: Bundle + 'static,
pub fn reserve<T>(&mut self, additional: u32)where T: Bundle + 'static,
Ensure at least additional
entities with exact components T
can be spawned without reallocating
sourcepub fn query<Q>(&self) -> QueryBorrow<'_, Q>where
Q: Query,
pub fn query<Q>(&self) -> QueryBorrow<'_, Q>where Q: Query,
Efficiently iterate over all entities that have certain components, using dynamic borrow checking
Prefer query_mut
when concurrent access to the World
is not required.
Calling iter
on the returned value yields (Entity, Q)
tuples, where Q
is some query
type. A query type is any type for which an implementation of Query
exists, e.g. &T
,
&mut T
, a tuple of query types, or an Option
wrapping a query type, where T
is any
component type. Components queried with &mut
must only appear once. Entities which do not
have a component type referenced outside of an Option
will be skipped.
Entities are yielded in arbitrary order.
The returned QueryBorrow
can be further transformed with combinator methods; see its
documentation for details.
Iterating a query will panic if it would violate an existing unique reference or construct an invalid unique reference. This occurs when two simultaneously-active queries could expose the same entity. Simultaneous queries can access the same component type if and only if the world contains no entities that have all components required by both queries, assuming no other component borrows are outstanding.
Iterating a query yields references with lifetimes bound to the QueryBorrow
returned
here. To ensure those are invalidated, the return value of this method must be dropped for
its dynamic borrows from the world to be released. Similarly, lifetime rules ensure that
references obtained from a query cannot outlive the QueryBorrow
.
Example
let mut world = World::new();
let a = world.spawn((123, true, "abc"));
let b = world.spawn((456, false));
let c = world.spawn((42, "def"));
let entities = world.query::<(&i32, &bool)>()
.iter()
.map(|(e, (&i, &b))| (e, i, b)) // Copy out of the world
.collect::<Vec<_>>();
assert_eq!(entities.len(), 2);
assert!(entities.contains(&(a, 123, true)));
assert!(entities.contains(&(b, 456, false)));
sourcepub fn query_one<Q>(
&self,
entity: Entity
) -> Result<QueryOne<'_, Q>, NoSuchEntity>where
Q: Query,
pub fn query_one<Q>( &self, entity: Entity ) -> Result<QueryOne<'_, Q>, NoSuchEntity>where Q: Query,
Prepare a query against a single entity, using dynamic borrow checking
Prefer query_one_mut
when concurrent access to the World
is not
required.
Call get
on the resulting QueryOne
to actually execute the query. The
QueryOne
value is responsible for releasing the dynamically-checked borrow made by
get
, so it can’t be dropped while references returned by get
are live.
Handy for accessing multiple components simultaneously.
Example
let mut world = World::new();
let a = world.spawn((123, true, "abc"));
// The returned query must outlive the borrow made by `get`
let mut query = world.query_one::<(&mut i32, &bool)>(a).unwrap();
let (number, flag) = query.get().unwrap();
if *flag { *number *= 2; }
assert_eq!(*number, 246);
sourcepub fn query_one_mut<Q>(
&mut self,
entity: Entity
) -> Result<<Q as Query>::Item<'_>, QueryOneError>where
Q: Query,
pub fn query_one_mut<Q>( &mut self, entity: Entity ) -> Result<<Q as Query>::Item<'_>, QueryOneError>where Q: Query,
sourcepub fn get<'a, T>(
&'a self,
entity: Entity
) -> Result<<T as ComponentRef<'a>>::Ref, ComponentError>where
T: ComponentRef<'a>,
pub fn get<'a, T>( &'a self, entity: Entity ) -> Result<<T as ComponentRef<'a>>::Ref, ComponentError>where T: ComponentRef<'a>,
Short-hand for entity
followed by EntityRef::get
sourcepub fn satisfies<Q>(&self, entity: Entity) -> Result<bool, NoSuchEntity>where
Q: Query,
pub fn satisfies<Q>(&self, entity: Entity) -> Result<bool, NoSuchEntity>where Q: Query,
Short-hand for entity
followed by EntityRef::satisfies
sourcepub fn entity(&self, entity: Entity) -> Result<EntityRef<'_>, NoSuchEntity>
pub fn entity(&self, entity: Entity) -> Result<EntityRef<'_>, NoSuchEntity>
Access an entity regardless of its component types
Does not immediately borrow any component.
sourcepub unsafe fn find_entity_from_id(&self, id: u32) -> Entity
pub unsafe fn find_entity_from_id(&self, id: u32) -> Entity
Given an id obtained from Entity::id
, reconstruct the still-live Entity
.
Safety
id
must correspond to a currently live Entity
. A despawned or never-allocated id
will produce undefined behavior.
sourcepub fn iter(&self) -> Iter<'_> ⓘ
pub fn iter(&self) -> Iter<'_> ⓘ
Iterate over all entities in the world
Entities are yielded in arbitrary order. Prefer query
for better
performance when components will be accessed in predictable patterns.
Example
let mut world = World::new();
let a = world.spawn(());
let b = world.spawn(());
let ids = world.iter().map(|entity_ref| entity_ref.entity()).collect::<Vec<_>>();
assert_eq!(ids.len(), 2);
assert!(ids.contains(&a));
assert!(ids.contains(&b));
sourcepub fn insert(
&mut self,
entity: Entity,
components: impl DynamicBundle
) -> Result<(), NoSuchEntity>
pub fn insert( &mut self, entity: Entity, components: impl DynamicBundle ) -> Result<(), NoSuchEntity>
Add components
to entity
Computational cost is proportional to the number of components entity
has. If an entity
already has a component of a certain type, it is dropped and replaced.
When inserting a single component, see insert_one
for convenience.
Example
let mut world = World::new();
let e = world.spawn((123, "abc"));
world.insert(e, (456, true));
assert_eq!(*world.get::<&i32>(e).unwrap(), 456);
assert_eq!(*world.get::<&bool>(e).unwrap(), true);
sourcepub fn insert_one(
&mut self,
entity: Entity,
component: impl Component
) -> Result<(), NoSuchEntity>
pub fn insert_one( &mut self, entity: Entity, component: impl Component ) -> Result<(), NoSuchEntity>
Add component
to entity
See insert
.
sourcepub fn remove<T>(&mut self, entity: Entity) -> Result<T, ComponentError>where
T: Bundle + 'static,
pub fn remove<T>(&mut self, entity: Entity) -> Result<T, ComponentError>where T: Bundle + 'static,
Remove components from entity
Computational cost is proportional to the number of components entity
has. The entity
itself is not removed, even if no components remain; use despawn
for that. If any
component in T
is not present in entity
, no components are removed and an error is
returned.
When removing a single component, see remove_one
for convenience.
Example
let mut world = World::new();
let e = world.spawn((123, "abc", true));
assert_eq!(world.remove::<(i32, &str)>(e), Ok((123, "abc")));
assert!(world.get::<&i32>(e).is_err());
assert!(world.get::<&&str>(e).is_err());
assert_eq!(*world.get::<&bool>(e).unwrap(), true);
sourcepub fn remove_one<T>(&mut self, entity: Entity) -> Result<T, ComponentError>where
T: Component,
pub fn remove_one<T>(&mut self, entity: Entity) -> Result<T, ComponentError>where T: Component,
Remove the T
component from entity
See remove
.
sourcepub fn exchange<S, T>(
&mut self,
entity: Entity,
components: T
) -> Result<S, ComponentError>where
S: Bundle + 'static,
T: DynamicBundle,
pub fn exchange<S, T>( &mut self, entity: Entity, components: T ) -> Result<S, ComponentError>where S: Bundle + 'static, T: DynamicBundle,
Remove S
components from entity
and then add components
This has the same effect as calling remove::<S>
and then insert::<T>
,
but is more efficient as the intermediate archetype after removal but before insertion is skipped.
sourcepub fn exchange_one<S, T>(
&mut self,
entity: Entity,
component: T
) -> Result<S, ComponentError>where
S: Component,
T: Component,
pub fn exchange_one<S, T>( &mut self, entity: Entity, component: T ) -> Result<S, ComponentError>where S: Component, T: Component,
Remove the S
component from entity
and then add component
See exchange
.
sourcepub unsafe fn get_unchecked<'a, T>(
&'a self,
entity: Entity
) -> Result<T, ComponentError>where
T: ComponentRef<'a>,
pub unsafe fn get_unchecked<'a, T>( &'a self, entity: Entity ) -> Result<T, ComponentError>where T: ComponentRef<'a>,
Borrow a single component of entity
without safety checks
T
must be a shared or unique reference to a component type.
Should only be used as a building block for safe abstractions.
Safety
entity
must have been previously obtained from this World
, and no unique borrow of the
same component of entity
may be live simultaneous to the returned reference.
sourcepub fn flush(&mut self)
pub fn flush(&mut self)
Convert all reserved entities into empty entities that can be iterated and accessed
Invoked implicitly by operations that add or remove components or entities, i.e. all
variations of spawn
, despawn
, insert
, and remove
.
sourcepub fn archetypes(&self) -> impl ExactSizeIterator
pub fn archetypes(&self) -> impl ExactSizeIterator
Inspect the archetypes that entities are organized into
Useful for dynamically scheduling concurrent queries by checking borrows in advance, and for efficient serialization.
sourcepub fn take(&mut self, entity: Entity) -> Result<TakenEntity<'_>, NoSuchEntity>
pub fn take(&mut self, entity: Entity) -> Result<TakenEntity<'_>, NoSuchEntity>
Despawn entity
, yielding a DynamicBundle
of its components
Useful for moving entities between worlds.
sourcepub fn archetypes_generation(&self) -> ArchetypesGeneration
pub fn archetypes_generation(&self) -> ArchetypesGeneration
Returns a distinct value after archetypes
is changed
Store the current value after deriving information from archetypes
,
then check whether the value returned by this function differs before attempting an
operation that relies on its correctness. Useful for determining whether e.g. a concurrent
query execution plan is still correct.
The generation may be, but is not necessarily, changed as a result of adding or removing any entity or component.
Example
let mut world = World::new();
let initial_gen = world.archetypes_generation();
world.spawn((123, "abc"));
assert_ne!(initial_gen, world.archetypes_generation());
Trait Implementations§
source§impl<A> Extend<A> for Worldwhere
A: DynamicBundle,
impl<A> Extend<A> for Worldwhere A: DynamicBundle,
source§fn extend<T>(&mut self, iter: T)where
T: IntoIterator<Item = A>,
fn extend<T>(&mut self, iter: T)where T: IntoIterator<Item = A>,
source§fn extend_one(&mut self, item: A)
fn extend_one(&mut self, item: A)
extend_one
)source§fn extend_reserve(&mut self, additional: usize)
fn extend_reserve(&mut self, additional: usize)
extend_one
)