mirror of
https://github.com/bevyengine/bevy
synced 2024-11-23 13:13:49 +00:00
92 lines
2.3 KiB
Markdown
92 lines
2.3 KiB
Markdown
|
# B0001
|
||
|
|
||
|
To keep [Rust rules on references](https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html#the-rules-of-references) (either one mutable reference or any number of immutable references) on a component, it is not possible to have two queries on the same component when one request mutable access to it in the same system.
|
||
|
|
||
|
Erroneous code example:
|
||
|
|
||
|
```rust,should_panic
|
||
|
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_system(move_enemies_to_player)
|
||
|
.run();
|
||
|
}
|
||
|
```
|
||
|
|
||
|
This will panic, as it's not possible to have both a mutable and an immutable query on `Transform` at the same time.
|
||
|
|
||
|
You have two solutions:
|
||
|
|
||
|
Solution #1: use disjoint queries using [`Without`](https://docs.rs/bevy/*/bevy/ecs/query/struct.Without.html)
|
||
|
|
||
|
As a `Player` entity won't be an `Enemy` at the same time, those two queries will acutally never target the same entity. This can be encoded in the query filter with [`Without`](https://docs.rs/bevy/*/bevy/ecs/query/struct.Without.html):
|
||
|
|
||
|
```rust,no_run
|
||
|
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_system(move_enemies_to_player)
|
||
|
.run();
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Solution #2: use a [`QuerySet`](https://docs.rs/bevy/*/bevy/ecs/system/struct.QuerySet.html)
|
||
|
|
||
|
A [`QuerySet`](https://docs.rs/bevy/*/bevy/ecs/system/struct.QuerySet.html) will let you have conflicting queries as a parameter, but you will still be responsible of not using them at the same time in your system.
|
||
|
|
||
|
```rust,no_run
|
||
|
use bevy::prelude::*;
|
||
|
|
||
|
#[derive(Component)]
|
||
|
struct Player;
|
||
|
|
||
|
#[derive(Component)]
|
||
|
struct Enemy;
|
||
|
|
||
|
fn move_enemies_to_player(
|
||
|
mut transforms: QuerySet<(
|
||
|
QueryState<&mut Transform, With<Enemy>>,
|
||
|
QueryState<&Transform, With<Player>>,
|
||
|
)>,
|
||
|
) {
|
||
|
// ...
|
||
|
}
|
||
|
|
||
|
fn main() {
|
||
|
App::new()
|
||
|
.add_plugins(DefaultPlugins)
|
||
|
.add_system(move_enemies_to_player)
|
||
|
.run();
|
||
|
}
|
||
|
```
|