#bevy-ecs #bevy #entity #object #ecs #traversal #macro-derive

moonshine-object

Bevy实体很好。对象更好!😎

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 游戏开发

Download history 343/week @ 2024-05-04 2/week @ 2024-05-11 25/week @ 2024-05-18 3/week @ 2024-05-25 4/week @ 2024-06-01 5/week @ 2024-06-08 4/week @ 2024-06-15 1/week @ 2024-06-22 125/week @ 2024-06-29 28/week @ 2024-07-06 8/week @ 2024-07-13 151/week @ 2024-07-20 35/week @ 2024-07-27

338 每月下载量
2 个Crate中使用(通过 moonshine-core

MIT 许可证

37KB
577

🌴 Moonshine Object

crates.io downloads docs.rs license stars

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>来使这些情况更加人性化。

它表现得像EntityInstance<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!
        }
    }
}

⚠️ 与 EntityInstance<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