#bevy #reflection #component #query #world #entities #add-on

cuicui_reflect_query

Bevy 反射插件,用于从反射组件查询世界数据

2 个版本

0.1.1 2023年6月11日
0.1.0 2023年6月11日

#1746游戏开发

MIT/Apache

31KB
496

Bevy 可查询 Reflect

Bevy tracking Latest version MIT/Apache 2.0 Documentation

Bevy 的 ReflectComponent 允许从 EntityRefEntityMut 中提取值,这很有用,但通常不足以满足需求。

ReflectComponent 缺少用于 查询 反射对象的方法。没有这项功能,您将不得不 遍历所有 EntityRef 并检查它是否包含所需组件。这是 O(n)(其中 n实体总数),而查询单个实体的效率是 O(1)。

我们引入了 ReflectQueryable 来填补这一空白。

我应该使用这个包吗?

简而言之,如果您在问这个问题,您很可能不应该使用!

如果这份README的第二段对您来说有什么意义,也就是说,这不是完整的科技术语,您可能会想“哇!这是可能的!”那么,是的,宝贝,这就是为您准备的!

用法

首先,将此包作为依赖项添加到您的 Cargo.toml

[dependencies]
cuicui_reflect_query = "<current version>"

如果您需要在使用 ReflectQueryable 的现有 bevy 组件上,请参阅 功能部分

然后,您将结合使用 ReflectQueryableTypeRegistry 和一个具有独占访问权限的 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