B0001
为了保持 Rust 中关于引用规则(在一个组件上可以有一个可变引用或多个不可变引用),在同一个系统中,如果两个查询都请求对同一个组件进行可变访问,则无法实现。
错误代码示例
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut enemies: Query<&mut Transform, With<Enemy>>,
player: Query<&Transform, With<Player>>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, move_enemies_to_player)
.run();
}
这将导致崩溃,因为无法同时在 `Transform` 上进行可变查询和不可变查询。
你有两种解决方法
解决方案 #1:使用 Without
进行不相交查询
由于一个 `Player` 实体不会同时是一个 `Enemy`,这两个查询实际上永远不会针对同一个实体。这可以通过 Without
在查询过滤器中进行编码。
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut enemies: Query<&mut Transform, With<Enemy>>,
player: Query<&Transform, (With<Player>, Without<Enemy>)>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, move_enemies_to_player)
.run();
}
解决方案 #2:使用 `ParamSet`
使用 `ParamSet` 可以将冲突的查询作为参数传入,但仍然需要你自己负责不要在系统中同时使用它们。
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut transforms: ParamSet<(
Query<&mut Transform, With<Enemy>>,
Query<&Transform, With<Player>>,
)>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Update, move_enemies_to_player)
.run();
}