mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
Update Query
struct docs (#5741)
# Objective - Update `Query` docs with better terminology - add some performance remarks (Fixes #4742) ## Solution - See #4989. This PR is derived from it. It just includes changes to the `Query` struct docs.
This commit is contained in:
parent
59bf3c4cc9
commit
7511c9bfaa
1 changed files with 197 additions and 173 deletions
|
@ -9,112 +9,70 @@ use crate::{
|
|||
};
|
||||
use std::{any::TypeId, borrow::Borrow, fmt::Debug};
|
||||
|
||||
/// Provides scoped access to components in a [`World`].
|
||||
/// [System parameter] that provides selective access to the [`Component`] data stored in a [`World`].
|
||||
///
|
||||
/// Queries enable iteration over entities and their components as well as filtering them
|
||||
/// on certain conditions. A query matches its parameters against the world to produce a series
|
||||
/// of results. Each *query result* is a tuple of components (the same components defined
|
||||
/// in the query) that belong to the same entity.
|
||||
/// Enables access to [entity identifiers] and [components] from a system, without the need to directly access the world.
|
||||
/// Its iterators and getter methods return *query items*.
|
||||
/// Each query item is a type containing data relative to an entity.
|
||||
///
|
||||
/// Computational cost of queries is reduced by the fact that they have an internal archetype
|
||||
/// cache to avoid re-computing archetype matches on each query access.
|
||||
/// `Query` is a generic data structure that accepts two type parameters, both of which must implement the [`WorldQuery`] trait:
|
||||
///
|
||||
/// Query functionality is based on the [`WorldQuery`] trait. Both tuples of components
|
||||
/// (up to 16 elements) and query filters implement this trait.
|
||||
/// - **`Q` (query fetch).**
|
||||
/// The type of data contained in the query item.
|
||||
/// Only entities that match the requested data will generate an item.
|
||||
/// - **`F` (query filter).**
|
||||
/// A set of conditions that determines whether query items should be kept or discarded.
|
||||
/// This type parameter is optional.
|
||||
///
|
||||
/// `Query` accepts two type parameters:
|
||||
/// # System parameter declaration
|
||||
///
|
||||
/// 1. **Component access:** the components that an entity must have at the same time to yield
|
||||
/// a query result.
|
||||
/// 2. **Query filters (optional):** a predicate that ignores query results that don't match
|
||||
/// its conditions.
|
||||
/// A query should always be declared as a system parameter.
|
||||
/// This section shows the most common idioms involving the declaration of `Query`, emerging by combining [`WorldQuery`] implementors.
|
||||
///
|
||||
/// # Usage as system parameter
|
||||
/// ## Component access
|
||||
///
|
||||
/// A query is defined by declaring it as a system parameter. This section shows the various
|
||||
/// use cases of `Query` as a system parameter.
|
||||
///
|
||||
/// ## Immutable component access
|
||||
///
|
||||
/// The following example defines a query that gives an iterator over `(&ComponentA, &ComponentB)`
|
||||
/// tuples, where `ComponentA` and `ComponentB` belong to the same entity. Accessing components
|
||||
/// immutably helps system parallelization.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::component::Component;
|
||||
/// # use bevy_ecs::system::IntoSystem;
|
||||
/// # use bevy_ecs::system::Query;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// query: Query<(&ComponentA, &ComponentB)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// You can use the [`ReadOnlyWorldQuery`] trait to abstract over read only query generics:
|
||||
/// ```
|
||||
/// # use bevy_ecs::system::Query;
|
||||
/// # use bevy_ecs::query::{QueryItem, ReadOnlyWorldQuery};
|
||||
/// fn system<Q: ReadOnlyWorldQuery>(
|
||||
/// query: Query<Q>,
|
||||
/// ) {
|
||||
/// let _: Option<QueryItem<Q>> = query.iter().next();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Mutable component access
|
||||
///
|
||||
/// The following example is similar to the previous one, with the exception of `ComponentA`
|
||||
/// being accessed mutably here. Note that both mutable and immutable accesses are allowed
|
||||
/// in the same query.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::component::Component;
|
||||
/// # use bevy_ecs::system::IntoSystem;
|
||||
/// # use bevy_ecs::system::Query;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// // `ComponentA` is accessed mutably, while `ComponentB` is accessed immutably.
|
||||
/// mut query: Query<(&mut ComponentA, &ComponentB)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// Two systems cannot be executed in parallel if both access a certain component and
|
||||
/// at least one of the accesses is mutable, unless the schedule can verify that no entity
|
||||
/// could be found in both queries, as otherwise Rusts mutability Rules would be broken.
|
||||
///
|
||||
/// Similarly, a system cannot contain two queries that would break Rust's mutability Rules.
|
||||
/// If you need such Queries, you can use Filters to make the Queries disjoint or use a
|
||||
/// [`ParamSet`](super::ParamSet).
|
||||
///
|
||||
/// ## Entity ID access
|
||||
///
|
||||
/// Inserting [`Entity`](crate::entity::Entity) at any position in the type parameter tuple
|
||||
/// will give access to the entity ID.
|
||||
/// A query defined with a reference to a component as the query fetch type parameter can be used to generate items that refer to the data of said component.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// query: Query<(Entity, &ComponentA, &ComponentB)>
|
||||
/// # fn immutable_ref(
|
||||
/// // A component can be accessed by shared reference...
|
||||
/// query: Query<&ComponentA>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_ref);
|
||||
///
|
||||
/// # fn mutable_ref(
|
||||
/// // ... or by mutable reference.
|
||||
/// query: Query<&mut ComponentA>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(mutable_ref);
|
||||
/// ```
|
||||
///
|
||||
/// ## Query filtering
|
||||
///
|
||||
/// The second, optional type parameter of query, is used for filters can be added to filter
|
||||
/// out the query results that don't satisfy the given condition.
|
||||
/// Setting the query filter type parameter will ensure that each query item satisfies the given condition.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// // Just `ComponentA` data will be accessed, but only for entities that also contain
|
||||
/// // `ComponentB`.
|
||||
/// query: Query<&ComponentA, With<ComponentB>>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// ## `WorldQuery` tuples
|
||||
///
|
||||
/// Using tuples, each `Query` type parameter can contain multiple elements.
|
||||
///
|
||||
/// In the following example, two components are accessed simultaneously, and the query items are filtered on two conditions.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
|
@ -124,43 +82,33 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug};
|
|||
/// # struct ComponentB;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentC;
|
||||
/// # fn system(
|
||||
/// // `ComponentC` data won't be accessed, but only entities that contain it will be queried.
|
||||
/// query: Query<(&ComponentA, &ComponentB), With<ComponentC>>
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentD;
|
||||
/// # fn immutable_ref(
|
||||
/// query: Query<(&ComponentA, &ComponentB), (With<ComponentC>, Without<ComponentD>)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_ref);
|
||||
/// ```
|
||||
///
|
||||
/// If you need to apply more filters in a single query, group them into a tuple:
|
||||
/// ## Entity identifier access
|
||||
///
|
||||
/// The identifier of an entity can be made available inside the query item by including [`Entity`] in the query fetch type parameter.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentC;
|
||||
/// # fn system(
|
||||
/// // Similar to the previous query, but with the addition of a `Changed` filter.
|
||||
/// query: Query<(&ComponentA, &ComponentB), (With<ComponentC>, Changed<ComponentA>)>
|
||||
/// query: Query<(Entity, &ComponentA)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// The following list contains all the available query filters:
|
||||
///
|
||||
/// - [`Added`](crate::query::Added)
|
||||
/// - [`Changed`](crate::query::Changed)
|
||||
/// - [`With`](crate::query::With)
|
||||
/// - [`Without`](crate::query::Without)
|
||||
/// - [`Or`](crate::query::Or)
|
||||
///
|
||||
/// ## Optional component access
|
||||
///
|
||||
/// A component can be made optional in a query by wrapping it into an [`Option`]. In the
|
||||
/// following example, the query will iterate over components of both entities that contain
|
||||
/// `ComponentA` and `ComponentB`, and entities that contain `ComponentA` but not `ComponentB`.
|
||||
/// A component can be made optional in a query by wrapping it into an [`Option`].
|
||||
/// In this way, a query item can still be generated even if the queried entity does not contain the wrapped component.
|
||||
/// In this case, its corresponding value will be `None`.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
|
@ -169,86 +117,162 @@ use std::{any::TypeId, borrow::Borrow, fmt::Debug};
|
|||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// // Generates items for entities that contain `ComponentA`, and optionally `ComponentB`.
|
||||
/// query: Query<(&ComponentA, Option<&ComponentB>)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// If an entity does not contain a component, its corresponding query result value will be
|
||||
/// `None`. Optional components increase the number of entities a query has to match against,
|
||||
/// therefore they can hurt iteration performance, especially in the worst case scenario where
|
||||
/// the query solely consists of only optional components, since all entities will be iterated
|
||||
/// over.
|
||||
/// See the documentation for [`AnyOf`] to idiomatically declare many optional components.
|
||||
///
|
||||
/// ## Single component access
|
||||
/// See the [performance] section to learn more about the impact of optional components.
|
||||
///
|
||||
/// If just a single component needs to be accessed, using a tuple as the first type parameter
|
||||
/// of `Query` can be omitted.
|
||||
/// ## Disjoint queries
|
||||
///
|
||||
/// A system cannot contain two queries that break Rust's mutability rules.
|
||||
/// In this case, the [`Without`] filter can be used to disjoint them.
|
||||
///
|
||||
/// In the following example, two queries mutably access the same component.
|
||||
/// Executing this system will panic, since an entity could potentially match the two queries at the same time by having both `Player` and `Enemy` components.
|
||||
/// This would violate mutability rules.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct Health;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct Player;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct Enemy;
|
||||
/// #
|
||||
/// fn randomize_health(
|
||||
/// player_query: Query<&mut Health, With<Player>>,
|
||||
/// enemy_query: Query<&mut Health, With<Enemy>>,
|
||||
/// )
|
||||
/// # {}
|
||||
/// # let mut randomize_health_system = bevy_ecs::system::IntoSystem::into_system(randomize_health);
|
||||
/// # let mut world = World::new();
|
||||
/// # randomize_health_system.initialize(&mut world);
|
||||
/// # randomize_health_system.run((), &mut world);
|
||||
/// ```
|
||||
///
|
||||
/// Adding a `Without` filter will disjoint the queries.
|
||||
/// In this way, any entity that has both `Player` and `Enemy` components is excluded from both queries.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct MyComponent;
|
||||
/// # fn tuple_system(
|
||||
/// // This is correct, but can be avoided.
|
||||
/// query: Query<(&MyComponent,)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(tuple_system);
|
||||
///
|
||||
/// # fn non_tuple_system(
|
||||
/// // This is the preferred method.
|
||||
/// query: Query<&MyComponent>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(non_tuple_system);
|
||||
/// ```
|
||||
///
|
||||
/// # Usage of query results
|
||||
///
|
||||
/// Inside the body of the system function, the `Query` is available as a function parameter.
|
||||
/// This section shows various methods to access query results.
|
||||
///
|
||||
/// ## Iteration over every query result
|
||||
///
|
||||
/// The [`iter`](Self::iter) and [`iter_mut`](Self::iter_mut) methods are used to iterate
|
||||
/// over every query result. Refer to the
|
||||
/// [`Iterator` API docs](https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html)
|
||||
/// for advanced iterator usage.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// # struct Health;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # struct Player;
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// fn immutable_query_system(query: Query<(&ComponentA, &ComponentB)>) {
|
||||
/// for (a, b) in &query {
|
||||
/// // Here, `a` and `b` are normal references to components, relatively of
|
||||
/// // `&ComponentA` and `&ComponentB` types.
|
||||
/// }
|
||||
/// }
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_query_system);
|
||||
///
|
||||
/// fn mutable_query_system(mut query: Query<(&mut ComponentA, &ComponentB)>) {
|
||||
/// for (mut a, b) in &mut query {
|
||||
/// // Similar to the above system, but this time `ComponentA` can be accessed mutably.
|
||||
/// // Note the usage of `mut` in the tuple and the call to `iter_mut` instead of `iter`.
|
||||
/// }
|
||||
/// }
|
||||
/// # bevy_ecs::system::assert_is_system(mutable_query_system);
|
||||
/// # struct Enemy;
|
||||
/// #
|
||||
/// fn randomize_health(
|
||||
/// player_query: Query<&mut Health, (With<Player>, Without<Enemy>)>,
|
||||
/// enemy_query: Query<&mut Health, (With<Enemy>, Without<Player>)>,
|
||||
/// )
|
||||
/// # {}
|
||||
/// # let mut randomize_health_system = bevy_ecs::system::IntoSystem::into_system(randomize_health);
|
||||
/// # let mut world = World::new();
|
||||
/// # randomize_health_system.initialize(&mut world);
|
||||
/// # randomize_health_system.run((), &mut world);
|
||||
/// ```
|
||||
///
|
||||
/// ## Getting the query result for a particular entity
|
||||
/// An alternative to this idiom is to wrap the conflicting queries into a [`ParamSet`](super::ParamSet).
|
||||
///
|
||||
/// If you have an [`Entity`] ID, you can use the [`get`](Self::get) or
|
||||
/// [`get_mut`](Self::get_mut) methods to access the query result for that particular entity.
|
||||
/// # Accessing query items
|
||||
///
|
||||
/// ## Getting a single query result
|
||||
/// The following table summarizes the behavior of the safe methods that can be used to get query items.
|
||||
///
|
||||
/// While it's possible to get a single result from a query by using `iter.next()`, a more
|
||||
/// idiomatic approach would use the [`single`](Self::single) or [`single_mut`](Self::single_mut)
|
||||
/// methods instead. Keep in mind though that they will return a [`QuerySingleError`] if the
|
||||
/// number of query results differ from being exactly one. If that's the case, use `iter.next()`
|
||||
/// (or `iter_mut.next()`) to only get the first query result.
|
||||
/// |Query methods|Effect|
|
||||
/// |:---:|---|
|
||||
/// |[`iter`]\([`_mut`][`iter_mut`])|Returns an iterator over all query items.|
|
||||
/// |[`for_each`]\([`_mut`][`for_each_mut`]),<br>[`par_for_each`]\([`_mut`][`par_for_each_mut`])|Runs a specified function for each query item.|
|
||||
/// |[`iter_many`]\([`_mut`][`iter_many_mut`])|Iterates or runs a specified function over query items generated by a list of entities.|
|
||||
/// |[`iter_combinations`]\([`_mut`][`iter_combinations_mut`])|Returns an iterator over all combinations of a specified number of query items.|
|
||||
/// |[`get`]\([`_mut`][`get_mut`])|Returns the query item for the specified entity.|
|
||||
/// |[`many`]\([`_mut`][`many_mut`]),<br>[`get_many`]\([`_mut`][`get_many_mut`])|Returns the query items for the specified entities.|
|
||||
/// |[`single`]\([`_mut`][`single_mut`]),<br>[`get_single`]\([`_mut`][`get_single_mut`])|Returns the query item while verifying that there aren't others.|
|
||||
///
|
||||
/// There are two methods for each type of query operation: immutable and mutable (ending with `_mut`).
|
||||
/// When using immutable methods, the query items returned are of type [`ROQueryItem`], a read-only version of the query item.
|
||||
/// In this circumstance, every mutable reference in the query fetch type parameter is substituted by a shared reference.
|
||||
///
|
||||
/// # Performance
|
||||
///
|
||||
/// Creating a `Query` is a low-cost constant operation.
|
||||
/// Iterating it, on the other hand, fetches data from the world and generates items, which can have a significant computational cost.
|
||||
///
|
||||
/// [`Table`] component storage type is much more optimized for query iteration than [`SparseSet`].
|
||||
///
|
||||
/// Two systems cannot be executed in parallel if both access the same component type where at least one of the accesses is mutable.
|
||||
/// This happens unless the executor can verify that no entity could be found in both queries.
|
||||
///
|
||||
/// Optional components increase the number of entities a query has to match against.
|
||||
/// This can hurt iteration performance, especially if the query solely consists of only optional components, since the query would iterate over each entity in the world.
|
||||
///
|
||||
/// The following table compares the computational complexity of the various methods and operations, where:
|
||||
///
|
||||
/// - **n** is the number of entities that match the query,
|
||||
/// - **r** is the number of elements in a combination,
|
||||
/// - **k** is the number of involved entities in the operation,
|
||||
/// - **a** is the number of archetypes in the world,
|
||||
/// - **C** is the [binomial coefficient], used to count combinations.
|
||||
/// <sub>n</sub>C<sub>r</sub> is read as "*n* choose *r*" and is equivalent to the number of distinct unordered subsets of *r* elements that can be taken from a set of *n* elements.
|
||||
///
|
||||
/// |Query operation|Computational complexity|
|
||||
/// |:---:|:---:|
|
||||
/// |[`iter`]\([`_mut`][`iter_mut`])|O(n)|
|
||||
/// |[`for_each`]\([`_mut`][`for_each_mut`]),<br>[`par_for_each`]\([`_mut`][`par_for_each_mut`])|O(n)|
|
||||
/// |[`iter_many`]\([`_mut`][`iter_many_mut`])|O(k)|
|
||||
/// |[`iter_combinations`]\([`_mut`][`iter_combinations_mut`])|O(<sub>n</sub>C<sub>r</sub>)|
|
||||
/// |[`get`]\([`_mut`][`get_mut`])|O(1)|
|
||||
/// |([`get_`][`get_many`])[`many`]|O(k)|
|
||||
/// |([`get_`][`get_many_mut`])[`many_mut`]|O(k<sup>2</sup>)|
|
||||
/// |[`single`]\([`_mut`][`single_mut`]),<br>[`get_single`]\([`_mut`][`get_single_mut`])|O(a)|
|
||||
/// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)|
|
||||
/// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)|
|
||||
///
|
||||
/// `for_each` methods are seen to be generally faster than their `iter` version on worlds with high archetype fragmentation.
|
||||
/// As iterators are in general more flexible and better integrated with the rest of the Rust ecosystem,
|
||||
/// it is advised to use `iter` methods over `for_each`.
|
||||
/// It is strongly advised to only use `for_each` if it tangibly improves performance:
|
||||
/// be sure profile or benchmark both before and after the change.
|
||||
///
|
||||
/// [`Added`]: crate::query::Added
|
||||
/// [`AnyOf`]: crate::query::AnyOf
|
||||
/// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient
|
||||
/// [`Changed`]: crate::query::Changed
|
||||
/// [components]: crate::component::Component
|
||||
/// [entity identifiers]: crate::entity::Entity
|
||||
/// [`for_each`]: Self::for_each
|
||||
/// [`for_each_mut`]: Self::for_each_mut
|
||||
/// [`get`]: Self::get
|
||||
/// [`get_many`]: Self::get_many
|
||||
/// [`get_many_mut`]: Self::get_many_mut
|
||||
/// [`get_mut`]: Self::get_mut
|
||||
/// [`get_single`]: Self::get_single
|
||||
/// [`get_single_mut`]: Self::get_single_mut
|
||||
/// [`iter`]: Self::iter
|
||||
/// [`iter_combinations`]: Self::iter_combinations
|
||||
/// [`iter_combinations_mut`]: Self::iter_combinations_mut
|
||||
/// [`iter_many`]: Self::iter_many
|
||||
/// [`iter_many_mut`]: Self::iter_many_mut
|
||||
/// [`iter_mut`]: Self::iter_mut
|
||||
/// [`many`]: Self::many
|
||||
/// [`many_mut`]: Self::many_mut
|
||||
/// [`Or`]: crate::query::Or
|
||||
/// [`par_for_each`]: Self::par_for_each
|
||||
/// [`par_for_each_mut`]: Self::par_for_each_mut
|
||||
/// [performance]: #performance
|
||||
/// [`single`]: Self::single
|
||||
/// [`single_mut`]: Self::single_mut
|
||||
/// [`SparseSet`]: crate::storage::SparseSet
|
||||
/// [System parameter]: crate::system::SystemParam
|
||||
/// [`Table`]: crate::storage::Table
|
||||
/// [`With`]: crate::query::With
|
||||
/// [`Without`]: crate::query::Without
|
||||
pub struct Query<'world, 'state, Q: WorldQuery, F: WorldQuery = ()> {
|
||||
pub(crate) world: &'world World,
|
||||
pub(crate) state: &'state QueryState<Q, F>,
|
||||
|
|
Loading…
Add table
Reference in a new issue