2 个版本
0.1.1 | 2023年6月11日 |
---|---|
0.1.0 | 2023年6月11日 |
#1746 在 游戏开发
31KB
496 行
Bevy 可查询 Reflect
Bevy 的 ReflectComponent
允许从 EntityRef
或 EntityMut
中提取值,这很有用,但通常不足以满足需求。
ReflectComponent
缺少用于 查询 反射对象的方法。没有这项功能,您将不得不 遍历所有 EntityRef
并检查它是否包含所需组件。这是 O(n)(其中 n
是 实体总数),而查询单个实体的效率是 O(1)。
我们引入了 ReflectQueryable
来填补这一空白。
我应该使用这个包吗?
简而言之,如果您在问这个问题,您很可能不应该使用!
如果这份README的第二段对您来说有什么意义,也就是说,这不是完整的科技术语,您可能会想“哇!这是可能的!”那么,是的,宝贝,这就是为您准备的!
用法
首先,将此包作为依赖项添加到您的 Cargo.toml
[dependencies]
cuicui_reflect_query = "<current version>"
如果您需要在使用 ReflectQueryable
的现有 bevy 组件上,请参阅 功能部分。
然后,您将结合使用 ReflectQueryable
、TypeRegistry 和一个具有独占访问权限的
World
如下所示
use std::any::TypeId;
use bevy::prelude::{Reflect, ReflectComponent, Component, World};
use bevy::reflect::TypeRegistryInternal as TypeRegistry;
use cuicui_reflect_query::{ReflectQueryable, Ref};
#[derive(Debug, Clone, PartialEq, Component, Reflect, Default)]
#[reflect(Component, Queryable)]
struct Zoobazee {
bee: u32,
baboo: String,
}
fn reflect_query<'w>(world: &'w mut World, registry: &TypeRegistry) -> Ref<'w, dyn Reflect> {
let type_data = registry
.get_type_data::<ReflectQueryable>(TypeId::of::<Zoobazee>())
.unwrap();
let mut query = type_data.query(world);
for element in query.iter(world) {
println!("{element:?}");
}
type_data.get_single_ref(world).unwrap()
}
fn main() {
let mut world = bevy::prelude::World::new();
let mut type_registry = TypeRegistry::new();
type_registry.register::<Zoobazee>();
let component = Zoobazee {
bee: 32,
baboo: "zoobalong".to_string(),
};
world.spawn(component.clone());
let single_result = reflect_query(&mut world, &type_registry);
assert_eq!(single_result.downcast_ref(), Some(&component));
}
详细信息
ReflectQueryable
为动态值添加了查询方法
reflect_ref
:这与ReflectComponent::reflect
类似,但也包括更改条目数据。这允许以不可变方式读取反射组件上的更改条目。
此外,reflect_mut
方法的生命周期有限,这可能是解决这些问题的好方法。query{,_entities,_ref,_mut}
:遍历具有反射组件的所有实体。与world.query
类似,您需要在对返回值调用.query(world)
来遍历查询结果。get_single{,_entity,_ref,_mut}
与world.get_single
类似,只有当存在且仅存在一个包含反射组件的实体时,它才会返回一个值。
一些精度说明
_entity
变体返回一个Entity
或实体的迭代器,而不是组件的dyn Reflect
版本。_ref
变体返回一个Ref<_>
对象,它覆盖了_
,这让你以不可变的方式读取更改信息。请注意,Ref
不是bevy的Ref
,而是cuicui_reflect_query
中的实现。目前无法使用bevy的Ref
来完成此操作。
pub struct ReflectQueryableFns {
pub reflect_ref: fn(EntityRef) -> Option<Ref<dyn Reflect>>,
pub get_single: fn(&mut World) -> SingleResult<&dyn Reflect>,
pub get_single_entity: fn(&mut World) -> SingleResult<Entity>,
pub get_single_ref: fn(&mut World) -> SingleResult<Ref<dyn Reflect>>,
pub get_single_mut: fn(&mut World) -> SingleResult<Mut<dyn Reflect>>,
pub query: fn(&mut World) -> Querydyn,
pub query_entities: fn(&mut World) -> EntityQuerydyn,
pub query_ref: fn(&mut World) -> RefQuerydyn,
pub query_mut: fn(&mut World) -> MutQuerydyn,
}
基础bevy组件的实现
由于这不是bevy的一部分,我们需要将其添加到bevy组件中。
要为bevy组件添加ReflectQueryable
实现,请使用以下predefined::QueryablePlugin
use bevy::prelude::*;
use cuicui_reflect_query::predefined::QueryablePlugin;
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins)
// … bunch of plugins …
.add_plugin(QueryablePlugin);
// … bunch of other things
}
这个crate每个bevy功能都暴露一个特性,它们默认是关闭的,你必须显式启用它们才能将ReflectQueryable
注册为bevy组件。
register_core_pipeline
register_pbr
register_sprite
register_render
register_ui
register_text
然后按照以下方式添加它们
[dependencies]
cuicui_reflect_query = { version = "<current version>", features = ["register_…" ] }
请注意,你可以自己添加它们。但如果有任何缺失,请打开一个问题,很难确保我没有忘记任何事情。
为你自己的类型实现
就像ReflectComponent
一样,你需要为你自己的类型注册特质的详细信息。它看起来像这样
+ use cuicui_reflect_query::ReflectQueryable;
#[derive(Reflect, Component, Default)]
- #[reflect(Component)]
+ #[reflect(Component, Queryable)]
struct Zoobaroo {
bidoo: u32,
bubble: String,
padiwoop: AlphaMode,
}
确保使用app.register_type::<Zoobaroo>()
!然后你应该就可以正常使用了。
版本矩阵
bevy | 最新支持的版本 |
---|---|
0.10 | <当前版本> |
许可
版权所有 © 2023 Nicola Papale
此软件根据您选择许可为MIT或Apache 2.0。有关详细信息,请参阅cuicui
存储库根目录下的licenses
目录。
依赖
~18–58MB
~1M SLoC