gpt4 book ai didi

bevy - 如何在 Bevy 系统中进行嵌套查询?

转载 作者:行者123 更新时间:2023-12-04 03:56:37 25 4
gpt4 key购买 nike

我正在和 Bevy 一起制作一个小 boids 玩具,每个 boid 的速度/加速度取决于它周围 boid 的位置和速度值。这意味着对于每个 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
}
}
}
但是,我不确定如何使用 Bevy 中的查询来做到这一点。假设我有一个系统 move_boids :
fn move_boids(mut query: Query<&Boid>) {
for boid in &mut query.iter() {
// I can't iterate over *other* boids here
}
}
我收到类似这样的错误,因为我在两个循环中都可变地借用了 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
我不能对同一个查询进行嵌套迭代,所以我不确定获取每个 boid 周围 boid 信息的最佳方法。我应该将第一个查询中每个 boid 的位置和速度信息复制到 HashMap<Entity, BoidData> 中,然后在其中进行查找吗?有什么我可以做的更惯用的吗?

最佳答案

所以我想出了一个非常不雅的答案,我不确定它是否适用于 boid。由于在同一范围内有两个可变引用,您尝试执行的操作将不起作用。
我能够获得其他 boid,并使用它们的 Vec<u128> 来比较它们。我不会使用哈希图,因为我听说他们的查找速度较慢,但​​我还没有尝试过。
我假设在我的例子中有恒定数量的 boid,但你可以只使用 boid 向量的长度。我还为我的示例编写了一个随机的 boid 结构并使用了 rand。

const NUM_BOIDS: u32 = 10;
struct Boids(Vec<u128>);
struct Boid {
position: f32,
velocity: f32,
}
fn main() {
App::build()
...
.add_resource(Boids(Vec::new()))
...
}

fn setup(mut commands: Commands, mut boids: ResMut<Boids>) {
let mut rng = rand::thread_rng();
for i in 0..10 {
// create 10 boids, and add there id's to the boids vec
if let Some(entity) = commands
.spawn((Boid {
position: rng.gen_range(0.0, 100.0),
velocity: rng.gen_range(0.0, 25.0),
},))
.current_entity()
{
boids.0.push(entity.id());
};
}
}

fn get_boids(mut boids: ResMut<Boids>, mut query: Query<(Entity, &mut Boid)>) {
// go through all the boid ids
for (i, boid_id) in boids.0.iter().enumerate() {
// go through a second time
for j in 0..NUM_BOIDS {
// this gets the next boid id unless its at the end
let other_boid_id = match boids.0.get(j as usize..(j as usize + 1)) {
Some(e) => e,
None => {
continue;
}
};
// skip if it is the same boid
if *boid_id == other_boid_id[0] {
continue;
}

// since you can't have two mutable references at the same time
// this gets the positions so those can be compared
// and if the statement is true, a mutable reference can be gotten again.
let mut first_position = 0.0;
{
let en = Entity::from_id(*boid_id);
let first_boid: RefMut<Boid> = query.get_mut::<Boid>(en).unwrap();
first_position = first_boid.position.clone();
}
let mut second_position = 0.0;
{
let en2 = Entity::from_id(other_boid_id[0]);
let second_boid: RefMut<Boid> = query.get_mut::<Boid>(en2).unwrap();
second_position = second_boid.position.clone();
}
if first_position - second_position < 0.001 {
let en = Entity::from_id(*boid_id);
let mut first_boid: RefMut<Boid> = query.get_mut::<Boid>(en).unwrap();
first_boid.velocity = 15.0;
}
}
}
}

关于bevy - 如何在 Bevy 系统中进行嵌套查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63768244/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com