Latest commit 85dac0c

事件

相关的官方文档:[event]


在系统间发送数据:

  • EventWriter<T>:发送事件
  • EventReader<T>:接收事件

每个Reader独立地追踪已读取的事件,因此可以处理来自多个系统的事件。

#![allow(unused)]
fn main() {
struct LevelUpEvent(Entity);

fn player_level_up(
    mut ev_levelup: EventWriter<LevelUpEvent>,
    query: Query<(Entity, &PlayerXp)>,
) {
    for (entity, xp) in query.iter() {
        if xp.0 > 1000 {
            ev_levelup.send(LevelUpEvent(entity));
        }
    }
}

fn debug_levelups(
    mut ev_levelup: EventReader<LevelUpEvent>,
) {
    for ev in ev_levelup.iter() {
        eprintln!("Entity {:?} level up!", ev.0);
    }
}
}

自定义事件要先在 [App Builder] 中注册:

fn main() {
    App::new()
        // ...
        .add_event::<LevelUpEvent>()
        .add_system(player_level_up)
        .add_system(debug_levelups)
        // ...
        .run();
}

事件应该是首选的数据流工具,因为事件可以从任何系统发送,并由多个系统接收,用途广泛。

隐藏的陷阱

注意 [Avoiding Frame Delays / 1-frame-lag]。如果Bevy在发送事件的系统之前先运行了接收事件的系统,就会出现这种情况。接收事件的系统只能在下一帧更新时接收事件。如果要在发送事件的同一帧立即接收事件,可以用 [System Order of Execution]。

事件不能持久。事件的储存时间是当前帧到下一帧结束前,之后就会丢失。如果某个处理事件的系统不是每帧运行,就会错过一些事件。这种设计好处是不用担心内存浪费在未处理的事件上。

如果希望事件能持久,可以[手动控制何时清除事件](忘记清除事件会浪费内存,甚至导致内存泄露)。