执行条件
执行条件是一种机制,用于控制 Bevy 在运行时是否应该执行特定的系统。这就是你控制如何使功能只在特定条件下被执行。
执行条件是一个较底层的基本功能。Bevy 在上面提供了更高层次的抽象,比如 状态。如果你真的需要更直接的控制,你可以使用执行条件,而不使用这些抽象概念。
执行条件也是 Bevy 系统,它返回一个类型为 enum ShouldRun
的值。它们可以接受任何系统参数,就像普通系统一样。
这个例子显示了如何使用执行条件来实现不同的多人游戏模式:
use bevy::ecs::schedule::ShouldRun;
#[derive(Debug, PartialEq, Eq)]
enum MultiplayerKind {
Client,
Host,
Local,
}
fn run_if_connected(
mode: Res<MultiplayerKind>,
session: Res<MyNetworkSession>,
) -> ShouldRun
{
if *mode == MultiplayerKind::Client && session.is_connected() {
ShouldRun::Yes
} else {
ShouldRun::No
}
}
fn run_if_host(
mode: Res<MultiplayerKind>,
) -> ShouldRun
{
if *mode == MultiplayerKind::Host || *mode == MultiplayerKind::Local {
ShouldRun::Yes
} else {
ShouldRun::No
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// if we are currently connected to a server,
// activate our client systems
.add_system_set(
SystemSet::new()
.with_run_criteria(run_if_connected)
.before("input")
.with_system(server_session)
.with_system(fetch_server_updates)
)
// if we are hosting the game,
// activate our game hosting systems
.add_system_set(
SystemSet::new()
.with_run_criteria(run_if_host)
.before("input")
.with_system(host_session)
.with_system(host_player_movement)
.with_system(host_enemy_ai)
)
// other systems in our game
.add_system(smoke_particles)
.add_system(water_animation)
.add_system_set(
SystemSet::new()
.label("input")
.with_system(keyboard_input)
.with_system(gamepad_input)
)
.run();
}
执行条件标签
如果你有多个系统或系统集,你想共享同一个执行标准,你可以给这个执行条件一个标签。
当你使用标签时,Bevy 将只执行一次执行条件系统,记住它的输出结果,并将结果应用于所有带有标签的任务。
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(RunCriteriaLabel)]
enum MyRunCriteria {
Client,
Host,
}
fn main() {
App::new()
// ...
.add_system_set(
SystemSet::new()
.with_run_criteria(
// assign it a label
run_if_host
.label(MyRunCriteria::Host)
)
.with_system(host_session)
.with_system(host_player_movement)
.with_system(host_enemy_ai)
)
// extra system for debugging the host
// it can share our previously-registered run criteria
.add_system(host_debug
.with_run_criteria(MyRunCriteria::Host)
)
.run();
}
如果你有一个复杂的执行条件系统,该系统会进行写操作或其他非幂等性操作,那么一次性执行的属性就特别重要。
已知的陷阱
当在一个不是每帧都被执行的系统中接收事件时,在接收系统不执行的帧中,所有发送的事件都将会错过。
为了应对这种情况,你可以实现一个自定义的事件清理策略,以便手动管理相关事件类型的生命周期。
Bevy 的固定时间步长在底层也是通过执行条件实现的。