pub unsafe trait QueryData: WorldQuery {
type ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>;
}
Expand description
Types that can be fetched from a World
using a Query
.
There are many types that natively implement this trait:
- Component references. (&T and &mut T) Fetches a component by reference (immutably or mutably).
QueryData
tuples. If every element of a tuple implementsQueryData
, then the tuple itself also implements the same trait. This enables a singleQuery
to access multiple components. Due to the current lack of variadic generics in Rust, the trait has been implemented for tuples from 0 to 15 elements, but nesting of tuples allows infiniteWorldQuery
s.Entity
. Gets the identifier of the queried entity.EntityLocation
. Gets the location metadata of the queried entity.EntityRef
. Read-only access to arbitrary components on the queried entity.EntityMut
. Mutable access to arbitrary components on the queried entity.&Archetype
. Read-only access to the archetype-level metadata of the queried entity.Option
. By default, a world query only tests entities that have the matching component types. Wrapping it into anOption
will increase the query search space, and it will returnNone
if an entity doesn’t satisfy theWorldQuery
.AnyOf
. Equivalent to wrapping each world query inside it into anOption
.Ref
. Similar to change detection filters but it is used as a query fetch parameter. It exposes methods to check for changes to the wrapped component.Has
. Returns a bool indicating whether the entity has the specified component.
Implementing the trait manually can allow for a fundamentally new type of behavior.
§Trait derivation
Query design can be easily structured by deriving QueryData
for custom types.
Despite the added complexity, this approach has several advantages over using QueryData
tuples.
The most relevant improvements are:
- Reusability across multiple systems.
- There is no need to destructure a tuple since all fields are named.
- Subqueries can be composed together to create a more complex query.
- Methods can be implemented for the query items.
- There is no hardcoded limit on the number of elements.
This trait can only be derived for structs, if each field also implements QueryData
.
use bevy_ecs::query::QueryData;
#[derive(QueryData)]
struct MyQuery {
entity: Entity,
// It is required that all reference lifetimes are explicitly annotated, just like in any
// struct. Each lifetime should be 'static.
component_a: &'static ComponentA,
component_b: &'static ComponentB,
}
fn my_system(query: Query<MyQuery>) {
for q in &query {
q.component_a;
}
}
§Macro expansion
Expanding the macro will declare one or three additional structs, depending on whether or not the struct is marked as mutable.
For a struct named X
, the additional structs will be:
Struct name | mutable only | Description |
---|---|---|
XItem | — | The type of the query item for X |
XReadOnlyItem | ✓ | The type of the query item for XReadOnly |
XReadOnly | ✓ | ReadOnly variant of X |
§Adding mutable references
Simply adding mutable references to a derived QueryData
will result in a compilation error:
#[derive(QueryData)]
struct CustomQuery {
component_a: &'static mut ComponentA,
}
To grant mutable access to components, the struct must be marked with the #[query_data(mutable)]
attribute.
This will also create three more structs that will be used for accessing the query immutably (see table above).
#[derive(QueryData)]
#[query_data(mutable)]
struct CustomQuery {
component_a: &'static mut ComponentA,
}
§Adding methods to query items
It is possible to add methods to query items in order to write reusable logic about related components.
This will often make systems more readable because low level logic is moved out from them.
It is done by adding impl
blocks with methods for the -Item
or -ReadOnlyItem
generated structs.
#[derive(Component)]
struct Health(f32);
#[derive(Component)]
struct Buff(f32);
#[derive(QueryData)]
#[query_data(mutable)]
struct HealthQuery {
health: &'static mut Health,
buff: Option<&'static mut Buff>,
}
// `HealthQueryItem` is only available when accessing the query with mutable methods.
impl<'w> HealthQueryItem<'w> {
fn damage(&mut self, value: f32) {
self.health.0 -= value;
}
fn total(&self) -> f32 {
self.health.0 + self.buff.as_deref().map_or(0.0, |Buff(buff)| *buff)
}
}
// `HealthQueryReadOnlyItem` is only available when accessing the query with immutable methods.
impl<'w> HealthQueryReadOnlyItem<'w> {
fn total(&self) -> f32 {
self.health.0 + self.buff.map_or(0.0, |Buff(buff)| *buff)
}
}
fn my_system(mut health_query: Query<HealthQuery>) {
// The item returned by the iterator is of type `HealthQueryReadOnlyItem`.
for health in health_query.iter() {
println!("Total: {}", health.total());
}
// The item returned by the iterator is of type `HealthQueryItem`.
for mut health in &mut health_query {
health.damage(1.0);
println!("Total (mut): {}", health.total());
}
}
§Deriving traits for query items
The QueryData
derive macro does not automatically implement the traits of the struct to the query item types.
Something similar can be done by using the #[query_data(derive(...))]
attribute.
This will apply the listed derivable traits to the query item structs.
#[derive(QueryData)]
#[query_data(mutable, derive(Debug))]
struct CustomQuery {
component_a: &'static ComponentA,
}
// This function statically checks that `T` implements `Debug`.
fn assert_debug<T: std::fmt::Debug>() {}
assert_debug::<CustomQueryItem>();
assert_debug::<CustomQueryReadOnlyItem>();
§Query composition
It is possible to use any QueryData
as a field of another one.
This means that a QueryData
can also be used as a subquery, potentially in multiple places.
#[derive(QueryData)]
struct SubQuery {
component_a: &'static ComponentA,
component_b: &'static ComponentB,
}
#[derive(QueryData)]
struct MyQuery {
subquery: SubQuery,
component_c: &'static ComponentC,
}
§Generic Queries
When writing generic code, it is often necessary to use PhantomData
to constrain type parameters. Since QueryData
is implemented for all
PhantomData<T>
types, this pattern can be used with this macro.
#[derive(QueryData)]
pub struct GenericQuery<T> {
id: Entity,
marker: PhantomData<T>,
}
§Safety
Component access of Self::ReadOnly
must be a subset of Self
and Self::ReadOnly
must match exactly the same archetypes/tables as Self
Required Associated Types§
Sourcetype ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>
type ReadOnly: ReadOnlyQueryData<State = <Self as WorldQuery>::State>
The read-only variant of this QueryData
, which satisfies the ReadOnlyQueryData
trait.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.
Implementations on Foreign Types§
Source§impl<'__w, T: Component> QueryData for &'__w mut T
impl<'__w, T: Component> QueryData for &'__w mut T
SAFETY: access of &T
is a subset of &mut T
Source§impl<F: QueryData> QueryData for (F₁, F₂, …, Fₙ)
impl<F: QueryData> QueryData for (F₁, F₂, …, Fₙ)
This trait is implemented for tuples up to 16 items long.
Source§impl<T: ?Sized> QueryData for PhantomData<T>
impl<T: ?Sized> QueryData for PhantomData<T>
SAFETY: Self::ReadOnly
is Self
type ReadOnly = PhantomData<T>
Implementors§
Source§impl QueryData for EntityLocation
impl QueryData for EntityLocation
SAFETY: Self
is the same as Self::ReadOnly
type ReadOnly = EntityLocation
Source§impl<'__w, T: Component> QueryData for Ref<'__w, T>
impl<'__w, T: Component> QueryData for Ref<'__w, T>
SAFETY: Self
is the same as Self::ReadOnly
Source§impl<'a> QueryData for FilteredEntityMut<'a>
impl<'a> QueryData for FilteredEntityMut<'a>
SAFETY: access of FilteredEntityRef
is a subset of FilteredEntityMut
type ReadOnly = FilteredEntityRef<'a>
Source§impl<'a> QueryData for FilteredEntityRef<'a>
impl<'a> QueryData for FilteredEntityRef<'a>
SAFETY: Self
is the same as Self::ReadOnly
type ReadOnly = FilteredEntityRef<'a>
Source§impl<'a, B> QueryData for EntityMutExcept<'a, B>where
B: Bundle,
impl<'a, B> QueryData for EntityMutExcept<'a, B>where
B: Bundle,
SAFETY: All accesses that EntityRefExcept
provides are also accesses that
EntityMutExcept
provides.
type ReadOnly = EntityRefExcept<'a, B>
Source§impl<'a, B> QueryData for EntityRefExcept<'a, B>where
B: Bundle,
impl<'a, B> QueryData for EntityRefExcept<'a, B>where
B: Bundle,
SAFETY: Self
is the same as Self::ReadOnly
.