5个版本
0.2.0 | 2024年7月21日 |
---|---|
0.1.3 | 2024年7月5日 |
0.1.2 | 2024年5月4日 |
0.1.1 | 2024年5月4日 |
0.1.0 | 2024年3月13日 |
#1188 in 游戏开发
338 每月下载量
在 2 个Crate中使用(通过 moonshine-core)
37KB
577 行
🌴 Moonshine Object
Bevy的扩展,提供了一种便于管理的接口,用于处理复杂的Entity
层次结构。
实体很好。对象更好!😎
概述
该Crate旨在为在Bevy中处理实体时的一些常用操作提供包装。
各种系统需要能够遍历复杂的实体层次结构,这是必须的。这在需要引用实体层次结构中各种实体的初始化代码时尤其如此。
例如,考虑一个系统,它通过扇动翅膀对飞翔的鸟做出反应
use bevy::prelude::*;
#[derive(Component)]
struct Bird;
#[derive(Component)]
struct Flying;
fn setup_bird(
query: Query<Entity, (With<Bird>, Added<Flying>)>,
children_query: Query<&Children>,
name: Query<&Name>,
mut commands: Commands
) {
for entity in query.iter() {
if let Ok(children) = children_query.get(entity) {
for child in children.iter() {
if let Ok(name) = name.get(*child) {
if name.as_str() == "Wings" {
if let Ok(wings) = children_query.get(*child) {
for wing in wings.iter() {
// TODO: Flap! Flap!
}
}
}
}
}
}
}
}
此代码故意冗长,以显示层次结构的复杂性。
此Crate通过引入Object<T>
来使这些情况更加人性化。
它表现得像Entity
或Instance<T>
,具有一些额外功能
use bevy::prelude::*;
use moonshine_object::prelude::*;
#[derive(Component)]
struct Bird;
#[derive(Component)]
struct Flying;
fn setup_bird(birds: Objects<Bird, Added<Flying>>, mut commands: Commands) {
for bird in birds.iter() {
if let Some(wings) = bird.find_by_path("./Wings") {
for wing in wings.children() {
// TODO: Flap! Flap!
}
}
}
}
特性
- 处理复杂的实体层次结构时,减少样板代码
- 通过
Kind
语义强制执行完全类型安全 - 没有宏!没有注册!
使用方法
对象<T>
使用Objects<T>
作为系统参数,以访问所有Object<T>
实例。
这个 SystemParam
被设计成类似于 Query
的用法
use bevy::prelude::*;
use moonshine_object::prelude::*;
#[derive(Component)]
struct Bird;
fn update_birds(birds: Objects<Bird>) {
for bird in birds.iter() {
// ...
}
}
类似于 Query
,您还可以使用 QueryFilter
use bevy::prelude::*;
use moonshine_object::prelude::*;
#[derive(Component)]
struct Bird;
#[derive(Component)]
struct Flying;
fn update_flying_birds(birds: Objects<Bird, With<Flying>>) {
for bird in birds.iter() {
// ...
}
}
内部,Objects<T>
仅仅是围绕一些常见查询的一个薄包装
查询<实例<T>>
Query<&Parent>
/Query<&Children>
查询<&名称>
对象<T>
每个 Object<T>
是一个指向 Entity
的引用,带有类型、名称和层次结构信息。这提供了一种方便的方式在函数之间传递这些数据
use bevy::prelude::*;
use moonshine_object::prelude::*;
#[derive(Component)]
struct Bird;
#[derive(Component)]
struct Flying;
fn update_flying_birds(birds: Objects<Bird, With<Flying>>) {
for bird in birds.iter() {
flap_wings(bird);
}
}
fn flap_wings(bird: Object<Bird>) {
if let Some(wings) = bird.find_by_path("./Wings") {
for wing in wings.children() {
// TODO: Flap! Flap!
}
}
}
⚠️ 与 Entity
或 Instance<T>
不同,Object<T>
具有非静态生命周期,不能用作 Query
术语。
类型转换
类似于 Instance<T>
,任何 Object<T>
都可以转换为 Object<U>
,如果 T
实现了 CastInto<U>
。
您可以使用 kind
宏为自己的类型实现此特性
use bevy::prelude::*;
use moonshine_kind::prelude::*;
use moonshine_object::prelude::*;
#[derive(Component)]
struct Bird;
struct Creature;
// Every Bird is a Creature by definition:
impl Kind for Creature {
type Filter = (With<Bird>, /* ... */);
}
// Therefore, all birds may safely be cast into creatures:
kind!(Bird is Creature);
// Birds can chirp.
fn chirp(bird: Object<Bird>) {
// TODO: Chirp!
}
// Creatures can find food.
fn find_food(creature: Object<Creature>) {
// TODO: Find food!
}
// Birds chirp when they get hungry.
fn handle_hunger(bird: Object<Bird>) {
chirp(bird);
find_food(bird.cast_into()); // Safe! :)
}
任何 Object<T>
都可以安全地转换为 Object<Any>
。
支持
请 提交问题 以报告任何错误、疑问或建议。
您还可以在官方 Bevy Discord 服务器上联系我作为 @Zeenobit。
依赖关系
~11MB
~197K SLoC