1

Amethyst Pong 教程中,对实体/组件/系统(ECS)架构的解释让我觉得系统是在main函数中添加到游戏中的东西,不能在运行时添加或删除。

在同一本书中,我按照这一部分添加了一个Producer系统和一个Receiver系统,它们都与定制的EventChannel.

由于ReceiverProducer是系统,按照教程我只学习了如何将它们添加到main函数中,而没有其他地方,而在代码示例中,Receiver'new方法是在World struct. 我没有任何关于Worldwhen 在main函数中的实例,因为在创建过程中似乎还为时过早,无法拥有其中之一。

如何以正确的 ECS 兼容方式完成?有没有办法在游戏循环期间从状态中检索系统并在那里订阅?会是正确的吗?

4

1 回答 1

1

回答有点晚了,但以防其他人遇到这个问题。

紫水晶书中给出的一些示例(在本例中为事件通道示例)依赖于捆绑您的系统,而不是直接将它们输入到 GameDataBuilder 中。

捆绑包在构建时可以访问世界对象。

请参阅官方紫水晶示例中的此示例,该示例展示了如何在系统构建中利用事件通道和访问世界对象。

https://github.com/amethyst/amethyst/tree/master/examples/events

例如:

# Custom Bundle.

#[derive(Debug)]
struct MyBundle;

impl<'a, 'b> SystemBundle<'a, 'b> for MyBundle {
    fn build(
        self,
        world: &mut World,
        builder: &mut DispatcherBuilder<'a, 'b>,
    ) -> Result<(), Error> {
        builder.add(SpammingSystem, "spamming_system", &[]);
        builder.add(
            ReceivingSystemDesc::default().build(world),
            "receiving_system",
            &[],
        );
        Ok(())
    }
}

# System.

#[derive(SystemDesc)]
#[system_desc(name(ReceivingSystemDesc))]
struct ReceivingSystem {
    #[system_desc(event_channel_reader)]
    reader: ReaderId<MyEvent>,
}

impl ReceivingSystem {
    pub fn new(reader: ReaderId<MyEvent>) -> Self {
        ReceivingSystem { reader }
    }
}

impl<'a> System<'a> for ReceivingSystem {
    type SystemData = Read<'a, EventChannel<MyEvent>>;

    fn run(&mut self, my_event_channel: Self::SystemData) {
        for event in my_event_channel.read(&mut self.reader) {
            println!("Received an event: {:?}", event);
        }
    }
}

# Adding your bundle.

fn main() -> amethyst::Result<()> {
    amethyst::start_logger(Default::default());

    let assets_dir = application_root_dir()?.join("examples/events/assets");

    let game_data = GameDataBuilder::default().with_bundle(MyBundle)?;

    let mut game = Application::build(assets_dir, GameplayState)?
        .with_frame_limit(FrameRateLimitStrategy::Sleep, 1)
        .build(game_data)?;

    game.run();
    Ok(())
}
于 2020-09-17T01:34:43.797 回答