为什么rust闭包fn()可以满足bevy的IntoSystemDescriptor特征< Params>

chhkpiq4  于 2023-05-18  发布在  其他
关注(0)|答案(1)|浏览(138)

有很多功能

fn add_people(mut commands: Commands) {
    commands.spawn((Person, Name("A".to_string())));
    commands.spawn((Person, Name("B".to_string())));
    commands.spawn((Person, Name("C".to_string())));
    commands.spawn((Person, Name("D".to_string())));
}

fn greet_people(query: Query<&Name, With<Person>>) {
    for name in query.iter() {
        println!("hello {}!", name.0);
    }
}
fn hello_world() {
    println!("hello world");
}

这些是我想调用的函数
pub fn add_startup_system(&mut self,system:impl IntoSystemDescriptor)
pub fn add_system(&mut self,system:impl IntoSystemDescriptor)
像这样

App::new()
        .add_plugins(DefaultPlugins)
        .add_startup_system(hello_world)
        .add_startup_system(add_people)
        .add_system(greet_people)
        .run();

以上函数类型为fn(Commands)fn(Query<&Name,With>)fn(),均满足目标IntoSystemDescriptor

IntoSystemDescriptor的定义是

pub trait IntoSystemDescriptor<Params> {
    fn into_descriptor(self) -> SystemDescriptor;
    /// Assigns a run criteria to the system. Can be a new descriptor or a label of a
    /// run criteria defined elsewhere.
    fn with_run_criteria<Marker>(
        self,
        run_criteria: impl IntoRunCriteria<Marker>,
    ) -> SystemDescriptor;

    /// Assigns a label to the system; there can be more than one, and it doesn't have to be unique.
    fn label(self, label: impl SystemLabel) -> SystemDescriptor;

    /// Specifies that the system should run before systems with the given label.
    fn before<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Specifies that the system should run after systems with the given label.
    fn after<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Marks this system as ambiguous with any system with the specified label.
    /// This means that execution order between these systems does not matter,
    /// which allows [some warnings](crate::schedule::ReportExecutionOrderAmbiguities) to be silenced.
    fn ambiguous_with<Marker>(self, label: impl AsSystemLabel<Marker>) -> SystemDescriptor;

    /// Specifies that this system should opt out of
    /// [execution order ambiguity detection](crate::schedule::ReportExecutionOrderAmbiguities).
    fn ignore_all_ambiguities(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems at the start of stage.
    fn at_start(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems after the parallel
    /// systems and before command buffer application.
    fn before_commands(self) -> SystemDescriptor;

    /// Specifies that the system should run with other exclusive systems at the end of stage.
    fn at_end(self) -> SystemDescriptor;
}

很难理解为什么fn实现了trait
看起来他们两个没有任何关系
谁能解释一下为什么fn满足这个特性?
或者给予我一个关于它的铁 rust 特征的链接

jdgnovmf

jdgnovmf1#

这是Bevy的核心特征之一。
Bevy是一个实体-组件-系统引擎。在Bevy之前还有其他的ECS引擎,比如Amethyst,但是Bevy让编写系统变得 * 容易 *。与其他引擎不同,系统不是一些特殊的结构体,而只是函数。他们只需要接受系统参数,你可以把这个函数给Bevy。Bevy会做所有的调度和参数传递(使用依赖注入),所以你不需要自己做所有这些。
您可以在the docs和第一个发行说明中阅读更多内容。
AFAIK,它是通过实现你为实现FnMut()FnMut(P1) where P1: IntoSystemParam,...,FnMut(P1, ..., PN) where P1: IntoSystemPara, ..., PN: IntoSystemParam中任何一个的任何类型F所示的trait来实现的。所有这些impls由宏。你可以看到这些实现here的列表。

相关问题