事件
可参考的官方例子:
[ecs_event
][example::ecs_event].
通过事件,可以在系统之间发送数据! 让你的系统之间相互沟通!
要发送事件,使用 EventWriter<T>
。要接收事件,使用 EventReader<T>
。
每个 reader 都独立地跟踪它所读取的事件,所以你可以处理来自多个系统的相同事件。
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 {:?} leveled up!", ev.0);
}
}
你需要通过应用程序生成器添加你的自定义事件类型:
fn main() {
App::new()
// ...
.add_event::<LevelUpEvent>()
.add_system(player_level_up)
.add_system(debug_levelups)
// ...
.run();
}
事件是你处理跳转类数据流的工具。由于事件可以从任何系统发送并被多个系统接收,因此它们的用途非常广泛。
可能的陷阱
小心帧延迟、帧滞后的问题,如果 Bevy 在发送系统之前运行接收系统,这样的问题可能会发生。接收系统只有在下一帧更新时才有机会接收事件。如果你需要确保事件被立即、在同一帧内处理,你可以使用显式系统排序。
事件不会持久化。它们被存储直到下一帧的结束,之后就会丢弃。如果你的系统不是每一帧都处理事件,你可能会错过一些事件。
这种设计的好处是,你不必担心未处理的事件会造成过多的内存占用。
如果你不喜欢这样,你可以手动控制事件被清除的时间(风险是如果你忘记清除它们,就有可能会内存泄漏和内存浪费)。