4个版本 (破坏性)
0.4.0 | 2024年7月6日 |
---|---|
0.3.0 | 2024年2月18日 |
0.2.0 | 2024年2月5日 |
0.1.0 | 2024年1月2日 |
#532 in 游戏开发
65 个月下载
23KB
323 行
bevy_consumable_event
一个用于向Bevy添加可消费事件的crate。
为什么?
Bevy中的事件非常强大。然而,它们有一个限制,那就是不能被消费。例如,如果你在UI上点击,理想情况下你只想让一个系统来处理那个点击。否则,点击一个UI元素也会点击其下的所有元素,使得“顺序”变得无关紧要。
用法
标准的用法是使用App::add_consumable_event
或App::add_persistent_consumable_event
(通过ConsumableEventApp
扩展特质)。这两个函数都允许你使用可消费事件,但它们决定了你何时可以读取和消费事件。
App::add_consumable_event
:事件将在每一帧的开始时被清除。因此,只有同一帧内并在ConsumableEventWriter
之后运行的系统才能读取事件。App::add_persistent_consumable_event
:事件不会被自动清除(除非已经消费的事件)。因此,事件将保持直到某个系统消费它们(或者你手动清除事件)。注意这意味着同一个系统可以多次读取同一个事件(因此它有多次消费事件的机会)。
为了消费一个事件,只需在从ConsumableEventReader
读取的项上调用consume()
即可。
use bevy::prelude::Event;
use bevy_consumable_event::ConsumableEventReader;
#[derive(Event)]
struct MyEvent;
fn consume_all_events(mut events: ConsumableEventReader<MyEvent>) {
for mut event in events.read() {
event.consume();
}
}
此外,你可以修改从ConsumableEventReader
读取的事件(这样后续的读取可以基于这些修改操作)。
虽然使用App::add_consumable_event
和App::add_persistent_consumable_event
是使用可消费事件的规范方法,就像常规事件一样,这些只是方便的。你也可以直接与ConsumableEvents
交互,并使用自定义清除策略,使用ConsumableEvents::clear
和ConsumableEvents::clear_consumed
。
示例
use bevy::{app::{ScheduleRunnerPlugin, RunMode}, prelude::*};
use bevy_consumable_event::{
ConsumableEventApp,
ConsumableEventReader,
ConsumableEventWriter,
};
fn main() {
App::new()
.add_plugins(ScheduleRunnerPlugin { run_mode: RunMode::Once })
.add_consumable_event::<MyEvent>()
.add_systems(Main, (
write_events,
consume_odds_and_add_ten_to_evens,
assert_remaining_events,
).chain()
)
.run();
}
#[derive(Event)]
struct MyEvent {
value: usize,
}
fn write_events(mut events: ConsumableEventWriter<MyEvent>) {
for value in 0..10 {
events.send(MyEvent { value });
}
}
fn consume_odds_and_add_ten_to_evens(
mut events: ConsumableEventReader<MyEvent>,
) {
for mut event in events.read() {
if event.value % 2 == 1 {
event.consume();
} else {
event.value += 10;
}
}
}
fn assert_remaining_events(mut events: ConsumableEventReader<MyEvent>) {
let values = events.read().map(|event| event.value).collect::<Vec<_>>();
assert_eq!(values, [10, 12, 14, 16, 18]);
}
注意事项
事件和消耗性事件不是互斥的 - 可以将类型添加为普通事件和消耗性事件。消耗性事件完全不与普通事件交互,所以一切都会正常工作。这可能会有些令人困惑。
事件也有多种策略来 1) 防止系统重复读取事件,2) 防止系统遗漏事件。对于消耗性事件,希望这些解决方案是不必要的。如果你使用非持久性消耗性事件,那么不应该发生重复读取(除了FixedUpdate系统)。无论如何,这些都是额外消耗事件的机会。遗漏事件是可以的,因为假设事件在帧的末尾被消耗。如果你确实使用持久性消耗性事件,则预期会发生重复读取。遗漏读取也不是问题,因为事件不会被清除。
许可证
在以下任一许可证下:
- Apache许可证版本2.0 (LICENSE-APACHE 或 http://www.apache.org/licenses/LICENSE-2.0)
- MIT许可证 (LICENSE-MIT 或 http://opensource.org/licenses/MIT)
任选其一。
贡献
欢迎贡献!
除非你明确表示,否则根据Apache-2.0许可证定义,你提交给作品的所有贡献都将双重许可,如上所述,不附加任何额外条款或条件。
依赖项
~11MB
~194K SLoC