Crate bevy_trait_query
source ·Expand description
Lets say you have a trait that you wanna implement for some of your components.
/// Components that display a message when hovered.
pub trait Tooltip {
/// Text displayed when hovering over an entity with this trait.
fn tooltip(&self) -> &str;
}
In order to be useful within bevy, you’ll want to be able to query for this trait.
ⓘ
// Just add this attribute...
#[bevy_trait_query::queryable]
pub trait Tooltip {
fn tooltip(&self) -> &str;
}
// ...and now you can use your trait in queries.
fn show_tooltips_system(
tooltips: Query<&dyn Tooltip>,
// ...
) {
// ...
}
Since Rust unfortunately lacks any kind of reflection, it is necessary to register each component with the trait when the app gets built.
#[derive(Component)]
struct Player(String);
#[derive(Component)]
enum Villager {
Farmer,
// ...
}
#[derive(Component)]
struct Monster;
/* ...trait implementations omitted for brevity... */
struct TooltipPlugin;
impl Plugin for TooltipPlugin {
fn build(&self, app: &mut App) {
// We must import this trait in order to register our components.
// If we don't register them, they will be invisible to the game engine.
use bevy_trait_query::RegisterExt;
app
.register_component_as::<dyn Tooltip, Player>()
.register_component_as::<dyn Tooltip, Villager>()
.register_component_as::<dyn Tooltip, Monster>()
.add_system(show_tooltips);
}
}
Unlike queries for concrete types, it’s possible for an entity to have multiple components that match a trait query.
fn show_tooltips(
tooltips: Query<&dyn Tooltip>,
// ...
) {
// Iterate over each entity that has tooltips.
for entity_tooltips in &tooltips {
// Iterate over each component implementing `Tooltip` for the current entity.
for tooltip in entity_tooltips {
println!("Tooltip: {}", tooltip.tooltip());
}
}
// If you instead just want to iterate over all tooltips, you can do:
for tooltip in tooltips.iter().flatten() {
println!("Tooltip: {}", tooltip.tooltip());
}
}
Alternatively, if you expect to only have component implementing the trait for each entity,
you can use the filter One
. This has significantly better performance than iterating
over all trait impls.
ⓘ
use bevy_trait_query::One;
fn show_tooltips(
tooltips: Query<One<&dyn Tooltip>>,
// ...
) {
for tooltip in &tooltips {
println!("Tooltip: {}", tooltip.tooltip());
}
}
Performance
The performance of trait queries is quite competitive. Here are some benchmarks for simple cases:
Concrete type | One | All | |
---|---|---|---|
1 match | 16.135 µs | 31.441 µs | 63.273 µs |
2 matches | 17.501 µs | - | 102.83 µs |
1-2 matches | - | 16.959 µs | 82.179 µs |
Modules
Structs
WorldQuery
adapter that fetches all implementations of a given trait for an entity.[
WorldQuery
] adapter that fetches entities with exactly one component implementing a trait.Read-access to all components implementing a trait for a given entity.
Write-access to all components implementing a trait for a given entity.
Traits
Extension methods for registering components with trait queries.
Marker for traits that can be used in queries.
Attribute Macros
When added to a trait declaration, generates the impls required to use that trait in queries.