Improve Query
's top-level documentation (#18622)
# Objective - There's been several changes to `Query` for this release cycle, and `Query`'s top-level documentation has gotten slightly out-of-date. - Alternative to #18615. ## Solution - Edit `Query`'s docs for consistency, clarity, and correctness. - Make sure to group `get()` and `get_many()` together instead of `single()` and `get_many()`, to enforce the distinction from https://github.com/bevyengine/bevy/pull/18615#issuecomment-2764355672. - Reformat doc tests so they would be readable if extracted into their own file. (Which mainly involves adding more spacing.) - Move link definitions to be nearer where they are used. - Fix the tables so they are up-to-date and correctly escape square brackets `\[ \]`. ## Testing I ran `cargo doc -p bevy_ecs --no-deps` to view the docs and `cargo test -p bevy_ecs --doc` to test the doc comments. ## Reviewing The diff is difficult to read, so I don't recommend _just_ looking at that. Instead, run `cargo doc -p bevy_ecs --no-deps` locally and read through the new version. It should theoretically read smoother with less super-technical jargon. :) ## Follow-up I want to go through some of `Query`'s methods, such as `single()`, `get()`, and `get_many()`, but I'll leave that for another PR. --------- Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
This commit is contained in:
parent
3d1335aeed
commit
4dcee649eb
@ -15,33 +15,40 @@ use core::{
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
/// [System parameter] that provides selective access to the [`Component`] data stored in a [`World`].
|
||||
/// A [system parameter] that provides selective access to the [`Component`] data stored in a [`World`].
|
||||
///
|
||||
/// 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.
|
||||
/// Queries enable systems to access [entity identifiers] and [components] without requiring direct access to the [`World`].
|
||||
/// Its iterators and getter methods return *query items*, which are types containing data related to an entity.
|
||||
///
|
||||
/// `Query` is a generic data structure that accepts two type parameters:
|
||||
///
|
||||
/// - **`D` (query data).**
|
||||
/// The type of data contained in the query item.
|
||||
/// - **`D` (query data)**:
|
||||
/// The type of data fetched by the query, which will be returned as the query item.
|
||||
/// Only entities that match the requested data will generate an item.
|
||||
/// Must implement the [`QueryData`] trait.
|
||||
/// - **`F` (query filter).**
|
||||
/// A set of conditions that determines whether query items should be kept or discarded.
|
||||
/// - **`F` (query filter)**:
|
||||
/// An optional set of conditions that determine whether query items should be kept or discarded.
|
||||
/// This defaults to [`unit`], which means no additional filters will be applied.
|
||||
/// Must implement the [`QueryFilter`] trait.
|
||||
/// This type parameter is optional.
|
||||
///
|
||||
/// [system parameter]: crate::system::SystemParam
|
||||
/// [`Component`]: crate::component::Component
|
||||
/// [`World`]: crate::world::World
|
||||
/// [entity identifiers]: Entity
|
||||
/// [components]: crate::component::Component
|
||||
///
|
||||
/// # Similar parameters
|
||||
///
|
||||
/// [`Query`] has few sibling [`SystemParam`](crate::system::system_param::SystemParam)s, which perform additional validation:
|
||||
/// `Query` has few sibling [`SystemParam`]s, which perform additional validation:
|
||||
///
|
||||
/// - [`Single`] - Exactly one matching query item.
|
||||
/// - [`Option<Single>`] - Zero or one matching query item.
|
||||
/// - [`Populated`] - At least one matching query item.
|
||||
///
|
||||
/// Those parameters will prevent systems from running if their requirements aren't met.
|
||||
/// These parameters will prevent systems from running if their requirements are not met.
|
||||
///
|
||||
/// [`SystemParam`]: crate::system::system_param::SystemParam
|
||||
/// [`Option<Single>`]: Single
|
||||
///
|
||||
/// # System parameter declaration
|
||||
///
|
||||
@ -50,330 +57,428 @@ use core::{
|
||||
///
|
||||
/// ## Component access
|
||||
///
|
||||
/// 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.
|
||||
/// You can fetch an entity's component by specifying a reference to that component in the query's data parameter:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # fn immutable_ref(
|
||||
/// // A component can be accessed by shared reference...
|
||||
/// query: Query<&ComponentA>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_ref);
|
||||
/// #
|
||||
/// // A component can be accessed by a shared reference...
|
||||
/// fn immutable_query(query: Query<&ComponentA>) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// # fn mutable_ref(
|
||||
/// // ... or by mutable reference.
|
||||
/// query: Query<&mut ComponentA>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(mutable_ref);
|
||||
/// // ...or by a mutable reference.
|
||||
/// fn mutable_query(query: Query<&mut ComponentA>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_query);
|
||||
/// # bevy_ecs::system::assert_is_system(mutable_query);
|
||||
/// ```
|
||||
///
|
||||
/// Note that components need to be behind a reference (`&` or `&mut`), or the query will not compile:
|
||||
///
|
||||
/// ```compile_fail,E0277
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// #
|
||||
/// // This needs to be `&ComponentA` or `&mut ComponentA` in order to compile.
|
||||
/// fn invalid_query(query: Query<ComponentA>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Query filtering
|
||||
///
|
||||
/// Setting the query filter type parameter will ensure that each query item satisfies 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);
|
||||
/// #
|
||||
/// // `ComponentA` data will be accessed, but only for entities that also contain `ComponentB`.
|
||||
/// fn filtered_query(query: Query<&ComponentA, With<ComponentB>>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(filtered_query);
|
||||
/// ```
|
||||
///
|
||||
/// Note that the filter is `With<ComponentB>`, not `With<&ComponentB>`. Unlike query data, `With`
|
||||
/// does require components to be behind a reference.
|
||||
///
|
||||
/// ## `QueryData` or `QueryFilter` tuples
|
||||
///
|
||||
/// Using tuples, each `Query` type parameter can contain multiple elements.
|
||||
/// Using [`tuple`]s, 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.
|
||||
/// In the following example two components are accessed simultaneously, and the query items are
|
||||
/// filtered on two conditions:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentC;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentD;
|
||||
/// # fn immutable_ref(
|
||||
/// query: Query<(&ComponentA, &ComponentB), (With<ComponentC>, Without<ComponentD>)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(immutable_ref);
|
||||
/// #
|
||||
/// fn complex_query(
|
||||
/// query: Query<(&mut ComponentA, &ComponentB), (With<ComponentC>, Without<ComponentD>)>
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(complex_query);
|
||||
/// ```
|
||||
///
|
||||
/// Note that this currently only works on tuples with 15 or fewer items. You may nest tuples to
|
||||
/// get around this limit:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentC;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentD;
|
||||
/// #
|
||||
/// fn nested_query(
|
||||
/// query: Query<(&ComponentA, &ComponentB, (&mut ComponentC, &mut ComponentD))>
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(nested_query);
|
||||
/// ```
|
||||
///
|
||||
/// ## 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.
|
||||
/// You can access [`Entity`], the entity identifier, by including it in the query data parameter:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # fn system(
|
||||
/// query: Query<(Entity, &ComponentA)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// #
|
||||
/// fn entity_id_query(query: Query<(Entity, &ComponentA)>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(entity_id_query);
|
||||
/// ```
|
||||
///
|
||||
/// Be aware that [`Entity`] is not a component, so it does not need to be behind a reference.
|
||||
///
|
||||
/// ## Optional component access
|
||||
///
|
||||
/// 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`.
|
||||
/// A component can be made optional by wrapping it into an [`Option`]. In the following example, a
|
||||
/// query item will still be generated even if the queried entity does not contain `ComponentB`.
|
||||
/// When this is the case, `Option<&ComponentB>`'s corresponding value will be `None`.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// #
|
||||
/// # #[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);
|
||||
/// #
|
||||
/// // A queried items must contain `ComponentA`. If they also contain `ComponentB`, its value will
|
||||
/// // be fetched as well.
|
||||
/// fn optional_component_query(query: Query<(&ComponentA, Option<&ComponentB>)>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(optional_component_query);
|
||||
/// ```
|
||||
///
|
||||
/// See the documentation for [`AnyOf`] to idiomatically declare many optional components.
|
||||
/// Optional components can hurt performance in some cases, so please read the [performance]
|
||||
/// section to learn more about them. Additionally, if you need to declare several optional
|
||||
/// components, you may be interested in using [`AnyOf`].
|
||||
///
|
||||
/// See the [performance] section to learn more about the impact of optional components.
|
||||
/// [performance]: #performance
|
||||
/// [`AnyOf`]: crate::query::AnyOf
|
||||
///
|
||||
/// ## 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.
|
||||
/// A system cannot contain two queries that break Rust's mutability rules, or else it will panic
|
||||
/// when initialized. This can often be fixed with the [`Without`] filter, which makes the queries
|
||||
/// disjoint.
|
||||
///
|
||||
/// 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.
|
||||
/// In the following example, the two queries can mutably access the same `&mut Health` component
|
||||
/// if an entity has both the `Player` and `Enemy` components. Bevy will catch this and panic,
|
||||
/// however, instead of breaking Rust's 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 = IntoSystem::into_system(randomize_health);
|
||||
/// # let mut world = World::new();
|
||||
/// # randomize_health_system.initialize(&mut world);
|
||||
/// # randomize_health_system.run((), &mut world);
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(randomize_health);
|
||||
/// ```
|
||||
///
|
||||
/// 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.
|
||||
/// Adding a [`Without`] filter will disjoint the queries. In the following example, any entity
|
||||
/// that has both the `Player` and `Enemy` components will be excluded from _both_ queries:
|
||||
///
|
||||
/// ```
|
||||
/// # 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>, Without<Enemy>)>,
|
||||
/// enemy_query: Query<&mut Health, (With<Enemy>, Without<Player>)>,
|
||||
/// )
|
||||
/// # {}
|
||||
/// # let mut randomize_health_system = IntoSystem::into_system(randomize_health);
|
||||
/// # let mut world = World::new();
|
||||
/// # randomize_health_system.initialize(&mut world);
|
||||
/// # randomize_health_system.run((), &mut world);
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(randomize_health);
|
||||
/// ```
|
||||
///
|
||||
/// An alternative to this idiom is to wrap the conflicting queries into a [`ParamSet`](super::ParamSet).
|
||||
/// An alternative solution to this problem would be to wrap the conflicting queries in
|
||||
/// [`ParamSet`].
|
||||
///
|
||||
/// [`Without`]: crate::query::Without
|
||||
/// [`ParamSet`]: crate::system::ParamSet
|
||||
///
|
||||
/// ## Whole Entity Access
|
||||
///
|
||||
/// [`EntityRef`]s can be fetched from a query. This will give read-only access to any component on the entity,
|
||||
/// and can be used to dynamically fetch any component without baking it into the query type. Due to this global
|
||||
/// access to the entity, this will block any other system from parallelizing with it. As such these queries
|
||||
/// should be sparingly used.
|
||||
/// [`EntityRef`] can be used in a query to gain read-only access to all components of an entity.
|
||||
/// This is useful when dynamically fetching components instead of baking them into the query type.
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # fn system(
|
||||
/// query: Query<(EntityRef, &ComponentA)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// #
|
||||
/// fn all_components_query(query: Query<(EntityRef, &ComponentA)>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(all_components_query);
|
||||
/// ```
|
||||
///
|
||||
/// As `EntityRef` can read any component on an entity, a query using it will conflict with *any* mutable
|
||||
/// access. It is strongly advised to couple `EntityRef` queries with the use of either `With`/`Without`
|
||||
/// filters or `ParamSets`. This also limits the scope of the query, which will improve iteration performance
|
||||
/// and also allows it to parallelize with other non-conflicting systems.
|
||||
/// As [`EntityRef`] can read any component on an entity, a query using it will conflict with *any*
|
||||
/// mutable component access.
|
||||
///
|
||||
/// ```should_panic
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # fn system(
|
||||
/// // This will panic!
|
||||
/// // EntityRef provides read access to ALL components on an entity.
|
||||
/// // When combined with &mut ComponentA in the same query, it creates
|
||||
/// // a conflict because EntityRef could read ComponentA while the &mut
|
||||
/// // attempts to modify it - violating Rust's borrowing rules of no
|
||||
/// // simultaneous read+write access.
|
||||
/// query: Query<(EntityRef, &mut ComponentA)>
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(system);
|
||||
/// #
|
||||
/// // `EntityRef` provides read access to *all* components on an entity. When combined with
|
||||
/// // `&mut ComponentA` in the same query, it creates a conflict because `EntityRef` could read
|
||||
/// // `&ComponentA` while `&mut ComponentA` attempts to modify it - violating Rust's borrowing
|
||||
/// // rules.
|
||||
/// fn invalid_query(query: Query<(EntityRef, &mut ComponentA)>) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(invalid_query);
|
||||
/// ```
|
||||
///
|
||||
/// It is strongly advised to couple [`EntityRef`] queries with the use of either [`With`] /
|
||||
/// [`Without`] filters or [`ParamSet`]s. Not only does this improve the performance and
|
||||
/// parallelization of the system, but it enables systems to gain mutable access to other
|
||||
/// components:
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentB;
|
||||
/// # fn system(
|
||||
/// // This will not panic.
|
||||
/// // This creates a perfect separation where:
|
||||
/// // 1. First query reads entities that have ComponentA
|
||||
/// // 2. Second query modifies ComponentB only on entities that DON'T have ComponentA
|
||||
/// // Result: No entity can ever be accessed by both queries simultaneously
|
||||
/// query_a: Query<EntityRef, With<ComponentA>>,
|
||||
/// query_b: Query<&mut ComponentB, Without<ComponentA>>,
|
||||
/// # ) {}
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(system);
|
||||
/// #
|
||||
/// // The first query only reads entities that have `ComponentA`, while the second query only
|
||||
/// // modifies entities that *don't* have `ComponentA`. Because neither query will access the same
|
||||
/// // entity, this system does not conflict.
|
||||
/// fn disjoint_query(
|
||||
/// query_a: Query<EntityRef, With<ComponentA>>,
|
||||
/// query_b: Query<&mut ComponentB, Without<ComponentA>>,
|
||||
/// ) {
|
||||
/// // ...
|
||||
/// }
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(disjoint_query);
|
||||
/// ```
|
||||
///
|
||||
/// The fundamental rule: [`EntityRef`]'s ability to read all components means it can never
|
||||
/// coexist with mutable access. With/Without filters guarantee this by keeping the
|
||||
/// coexist with mutable access. [`With`] / [`Without`] filters can guarantee this by keeping the
|
||||
/// queries on completely separate entities.
|
||||
///
|
||||
/// [`EntityRef`]: crate::world::EntityRef
|
||||
/// [`With`]: crate::query::With
|
||||
///
|
||||
/// # Accessing query items
|
||||
///
|
||||
/// The following table summarizes the behavior of the safe methods that can be used to get query items.
|
||||
/// The following table summarizes the behavior of safe methods that can be used to get query
|
||||
/// items:
|
||||
///
|
||||
/// |Query methods|Effect|
|
||||
/// |:---:|---|
|
||||
/// |[`iter`]\[[`_mut`][`iter_mut`]]|Returns an iterator over all query items.|
|
||||
/// |[[`iter().for_each()`][`for_each`]\[[`iter_mut().for_each()`][`for_each`]],<br>[`par_iter`]\[[`_mut`][`par_iter_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>[`single`]\[[`_mut`][`single_mut`]]|Returns the query item while verifying that there aren't others.|
|
||||
/// |-|-|
|
||||
/// |[`iter`]\[[`_mut`][`iter_mut`]\]|Returns an iterator over all query items.|
|
||||
/// |[`iter[_mut]().for_each()`][`for_each`],<br />[`par_iter`]\[[`_mut`][`par_iter_mut`]\]|Runs a specified function for each query item.|
|
||||
/// |[`iter_many`]\[[`_unique`][`iter_many_unique`]\]\[[`_mut`][`iter_many_mut`]\]|Iterates over query items that match a list of entities.|
|
||||
/// |[`iter_combinations`]\[[`_mut`][`iter_combinations_mut`]\]|Iterates over all combinations of query items.|
|
||||
/// |[`single`](Self::single)\[[`_mut`][`single_mut`]\]|Returns a single query item if only one exists.|
|
||||
/// |[`get`]\[[`_mut`][`get_mut`]\]|Returns the query item for a specified entity.|
|
||||
/// |[`get_many`]\[[`_unique`][`get_many_unique`]\]\[[`_mut`][`get_many_mut`]\]|Returns all query items that match a list of entities.|
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// [`iter`]: Self::iter
|
||||
/// [`iter_mut`]: Self::iter_mut
|
||||
/// [`for_each`]: #iteratorfor_each
|
||||
/// [`par_iter`]: Self::par_iter
|
||||
/// [`par_iter_mut`]: Self::par_iter_mut
|
||||
/// [`iter_many`]: Self::iter_many
|
||||
/// [`iter_many_unique`]: Self::iter_many_unique
|
||||
/// [`iter_many_mut`]: Self::iter_many_mut
|
||||
/// [`iter_combinations`]: Self::iter_combinations
|
||||
/// [`iter_combinations_mut`]: Self::iter_combinations_mut
|
||||
/// [`single_mut`]: Self::single_mut
|
||||
/// [`get`]: Self::get
|
||||
/// [`get_mut`]: Self::get_mut
|
||||
/// [`get_many`]: Self::get_many
|
||||
/// [`get_many_unique`]: Self::get_many_unique
|
||||
/// [`get_many_mut`]: Self::get_many_mut
|
||||
///
|
||||
/// # 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.
|
||||
/// 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. Because of this, it is recommended for queries to only
|
||||
/// fetch mutable access to components when necessary, since immutable access can be parallelized.
|
||||
///
|
||||
/// 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.
|
||||
/// Query filters ([`With`] / [`Without`]) can improve performance because they narrow the kinds of
|
||||
/// entities that can be fetched. Systems that access fewer kinds of entities are more likely to be
|
||||
/// parallelized by the scheduler.
|
||||
///
|
||||
/// 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.
|
||||
/// On the other hand, be careful using optional components (`Option<&ComponentA>`) and
|
||||
/// [`EntityRef`] because they broaden the amount of entities kinds that can be accessed. This is
|
||||
/// especially true of a query that _only_ fetches optional components or [`EntityRef`], as the
|
||||
/// query would iterate over all entities in the world.
|
||||
///
|
||||
/// The following table compares the computational complexity of the various methods and operations, where:
|
||||
/// There are two types of [component storage types]: [`Table`] and [`SparseSet`]. [`Table`] offers
|
||||
/// fast iteration speeds, but slower insertion and removal speeds. [`SparseSet`] is the opposite:
|
||||
/// it offers fast component insertion and removal speeds, but slower iteration speeds.
|
||||
///
|
||||
/// - **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.
|
||||
/// 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)|
|
||||
/// |[[`iter().for_each()`][`for_each`]\[[`iter_mut().for_each()`][`for_each`]],<br>[`par_iter`]\[[`_mut`][`par_iter_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>[`single`]\[[`_mut`][`single_mut`]]|O(a)|
|
||||
/// |Archetype based filtering ([`With`], [`Without`], [`Or`])|O(a)|
|
||||
/// |-|-|
|
||||
/// |[`iter`]\[[`_mut`][`iter_mut`]\]|O(n)|
|
||||
/// |[`iter[_mut]().for_each()`][`for_each`],<br/>[`par_iter`]\[[`_mut`][`par_iter_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>)|
|
||||
/// |[`single`](Self::single)\[[`_mut`][`single_mut`]\]|O(a)|
|
||||
/// |[`get`]\[[`_mut`][`get_mut`]\]|O(1)|
|
||||
/// |[`get_many`]|O(k)|
|
||||
/// |[`get_many_mut`]|O(k<sup>2</sup>)|
|
||||
/// |Archetype-based filtering ([`With`], [`Without`], [`Or`])|O(a)|
|
||||
/// |Change detection filtering ([`Added`], [`Changed`])|O(a + n)|
|
||||
///
|
||||
/// [component storage types]: crate::component::StorageType
|
||||
/// [`Table`]: crate::storage::Table
|
||||
/// [`SparseSet`]: crate::storage::SparseSet
|
||||
/// [binomial coefficient]: https://en.wikipedia.org/wiki/Binomial_coefficient
|
||||
/// [`Or`]: crate::query::Or
|
||||
/// [`Added`]: crate::query::Added
|
||||
/// [`Changed`]: crate::query::Changed
|
||||
///
|
||||
/// # `Iterator::for_each`
|
||||
///
|
||||
/// `for_each` methods are seen to be generally faster than directly iterating through `iter` on worlds with high archetype
|
||||
/// fragmentation, and may enable additional optimizations like [autovectorization]. It is strongly advised to only use
|
||||
/// [`Iterator::for_each`] if it tangibly improves performance. *Always* be sure profile or benchmark both before and
|
||||
/// after the change!
|
||||
/// The `for_each` methods appear to be generally faster than `for`-loops when run on worlds with
|
||||
/// high archetype fragmentation, and may enable additional optimizations like [autovectorization]. It
|
||||
/// is strongly advised to only use [`Iterator::for_each`] if it tangibly improves performance.
|
||||
/// *Always* profile or benchmark before and after the change!
|
||||
///
|
||||
/// ```rust
|
||||
/// # use bevy_ecs::prelude::*;
|
||||
/// #
|
||||
/// # #[derive(Component)]
|
||||
/// # struct ComponentA;
|
||||
/// # fn system(
|
||||
/// # query: Query<&ComponentA>,
|
||||
/// # ) {
|
||||
/// // This might be result in better performance...
|
||||
/// query.iter().for_each(|component| {
|
||||
/// // do things with the component
|
||||
/// });
|
||||
/// // ...than this. Always be sure to benchmark to validate the difference!
|
||||
/// for component in query.iter() {
|
||||
/// // do things with the component
|
||||
/// #
|
||||
/// fn system(query: Query<&ComponentA>) {
|
||||
/// // This may result in better performance...
|
||||
/// query.iter().for_each(|component| {
|
||||
/// // ...
|
||||
/// });
|
||||
///
|
||||
/// // ...than this. Always benchmark to validate the difference!
|
||||
/// for component in query.iter() {
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
/// # }
|
||||
/// # bevy_ecs::system::assert_system_does_not_conflict(system);
|
||||
/// #
|
||||
/// # bevy_ecs::system::assert_is_system(system);
|
||||
/// ```
|
||||
///
|
||||
/// [`Component`]: crate::component::Component
|
||||
/// [autovectorization]: https://en.wikipedia.org/wiki/Automatic_vectorization
|
||||
/// [`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]: Entity
|
||||
/// [`EntityRef`]: crate::world::EntityRef
|
||||
/// [`for_each`]: #iterator-for-each
|
||||
/// [`get`]: Self::get
|
||||
/// [`get_many`]: Self::get_many
|
||||
/// [`get_many_mut`]: Self::get_many_mut
|
||||
/// [`get_mut`]: Self::get_mut
|
||||
/// [`single`]: Self::single
|
||||
/// [`single_mut`]: Self::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_iter`]: Self::par_iter
|
||||
/// [`par_iter_mut`]: Self::par_iter_mut
|
||||
/// [performance]: #performance
|
||||
/// [`Single`]: Single
|
||||
/// [`Option<Single>`]: Single
|
||||
/// [`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, D: QueryData, F: QueryFilter = ()> {
|
||||
// SAFETY: Must have access to the components registered in `state`.
|
||||
world: UnsafeWorldCell<'world>,
|
||||
|
Loading…
Reference in New Issue
Block a user