Bevy如何基于参数类型对其系统进行"作用域"?

8

Bevy 是一个新的 Rust 游戏引擎和 ECS,它有一个特性,可以根据参数类型来 "范围化" 它的系统。来自它的文档

我们传递给 "系统函数" 的参数定义了系统运行的实体。在这种情况下,greet_people 将在所有具有 Person 和 Name 组件的实体上运行。

它看起来像这样:

struct Person;
struct Name(String);

fn greet_people(person: &Person, name: &Name) {
    println!("hello {}", name.0);
}

Bevy是如何实现这一点的?我记得在某个地方看到过Rust并不支持这种方式的反射。
1个回答

16
Bevy定义了一组特征(IntoSystem),这些特征适用于所有实现了SystemParamFunction/ExclusiveSystemParamFunction的函数,这些函数可以用作系统。然后,这些特征由Bevy预导出。其中一个限制是,您只能将具有一定数量参数的函数转换为系统,并且参数必须按照特定顺序([command?], [resources...], [queries/components...])排列。
您可以通过类似的方式自己实现这些特征。
trait MyTrait<Args> {
    fn invoke(&mut self, args: Args);
}

impl<F> MyTrait<()> for F
where
    F: FnMut() -> (),
{
    fn invoke(&mut self, (): ()) {
        (self)()
    }
}

// More impls for functions up to N arity...
// Usually a helper macro is used for this

fn test() {
    println!("Hello, world!");
}

fn main() {
    test.invoke(());
}

游乐场


1
Bevy ECS 的做法是正确的方式。框架的工作是处理样板代码,比如系统需求分析。当系统函数的签名已经展示了其要求时,用户没有具体需要手动标记宏或注册某些东西。 - Fifnmar
这算是一种取巧的方式吗?在学习这个库的时候,我感到相当困惑。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接