我正在与 Bevy 一起制作一个小boids玩具,每个 boids 的速度/加速度取决于它周围 boids 的位置和速度值。这意味着对于每个 boid,我想运行一些依赖于其他 boid 的某个子集的逻辑。
这看起来基本上可能是一个嵌套的 for 循环:
for boid in boids {
for other_boid in boids {
if boid.id == other_boid.id {
continue;
}
if boid.position.distance_to(other_boid.position) < PERCEPTION_DISTANCE {
// change boid's velocity / acceleration
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,我不确定如何在 Bevy 中进行查询。假设我有一个系统move_boids:
fn move_boids(mut query: Query<&Boid>) {
for boid in &mut query.iter() {
// I can't iterate over *other* boids here
}
}
Run Code Online (Sandbox Code Playgroud)
我收到类似这样的错误,因为我query在两个循环中都可变地借用:
error[E0499]: cannot borrow `query` as mutable more than once at a time
--> src\main.rs:10:32
|
10 | for boid in &mut query.iter() {
| ------------
| | |
| | ... and the first borrow might be used here, when that temporary is dropped and runs the `Drop` code for type `bevy::bevy_ecs::system::query::QueryBorrow`
| first mutable borrow occurs here
| a temporary with access to the first borrow is created here ...
...
11 | for other_boid in &mut query.iter() {}
| ^^^^^ second mutable borrow occurs here
Run Code Online (Sandbox Code Playgroud)
我无法对同一查询进行嵌套迭代,因此我不确定获取每个 boid 周围 boids 信息的最佳方法。我应该将每个主体的位置和速度信息从第一个查询复制到 a 中HashMap<Entity, BoidData>,然后在其中进行查找吗?我可以做一些更惯用的事情吗?
几年后回答我自己的问题。Bevy 0.6 版本引入了Query::iter_combinations和Query::iter_combinations_mut,后者正是您想要的。
因此,要使用问题中的示例系统,它看起来像这样:
fn move_boids(mut query: Query<&mut Boid>) {
let mut combinations = query.iter_combinations_mut();
while let Some([mut a, mut b]) = combinations.fetch_next() {
// update velocity and acceleration
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,来自 Bevy 文档:
返回的值不是
Iterator,因为这会导致可变引用的别名。为了迭代它,请使用fetch_next带有循环模式的方法while let Some(..)。
另请参阅Bevy 存储库中 iter_combinations 的官方示例。
| 归档时间: |
|
| 查看次数: |
3075 次 |
| 最近记录: |