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