手动清除事件
事件队列需要定期清理,这样它就不会无限制地增长和浪费无限制的内存。
Bevy 的默认清理策略是在每一帧都清除事件,但有双重缓冲,所以前一帧中产生的事件保持可用。这意味着你只能在事件发送后的下一帧结束之前处理这些事件。
这个默认策略对每一帧运行都会检查事件的系统很有效,这也是典型的用法模式。
然而,如果你的系统不是每一帧都读取事件,它们就会错过一些事件。出现这种情况的一些常见情况是:
为了能够在这类情况下可靠地管理事件,你可能想要手动的控制事件在内存中保留的时间。
你可以用你自己的策略取代 Bevy 的默认清理策略。
要做到这一点,只需使用 .init_resource
(而不是 .add_event
)方法将你的事件类型(封装为 Events<T>
)添加到应用程序构造器中。
(.add_event
实际上只是一个方便的方法,它初始化了资源并为默认的清理策略添加了 Bevy 的内置系统(事件类型泛型化))
然后你必须谨慎地清除事件。如果你不经常这样做,你的事件可能会堆积起来,浪费内存。
示例
我们可以为此创建泛型系统。实现自定义清理策略,然后根据需要多次将该系统添加到你的App
中,用于你想使用自定义行为的每个事件类型。
use bevy::app::Events;
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// add the `Events<T>` resource manually
// these events will not have automatic cleanup
.init_resource::<Events<MySpecialEvent>>()
// this is a regular event type with automatic cleanup
.add_event::<MyRegularEvent>()
// add the cleanup systems
.add_system(my_event_manager::<MySpecialEvent>)
.run();
}
/// Custom cleanup strategy for events
///
/// Generic to allow using for any custom event type
fn my_event_manager<T: 'static + Send + Sync>(
mut events: ResMut<Events<T>>,
) {
// TODO: implement your custom logic
// for deciding when to clear the events
// clear all events like this:
events.clear();
// or with double-buffering
// (this is what Bevy's default strategy does)
events.update();
// or drain them, if you want to iterate,
// to access the values:
for event in events.drain() {
// TODO: do something with each event
}
}