Legion ECS 的多个可变查询

Multiple mutable queries with Legion ECS

我正在使用 Legion ECS 并尝试将多个可变查询和 运行 用于一些借用检查器约束。

我基本上想通过与所有其他组件进行比较来更新组件的状态。

本质上 - 如果组件与另一个组件相邻,则将它们设为蓝色。

let components = <&Component>::query()
  .iter(world)
  .collect();

<&Component>::query()
  .iter_mut(world)
  .for_each(|component| {
     // for each c in components 
     // make component blue if c is adjacent to this component
   })

上面的错误是 cannot borrow *ecs as mutable more than once at a time

    |
128 |             .iter(&ecs)
    |                   ---- immutable borrow occurs here
...
134 |             .iter_mut(&mut ecs)
    |                       ^^^^^^^^ mutable borrow occurs here
135 |             .for_each(|(_, fov)| {
136 |                 let fovs: HashSet<Point> = components
    |                                            --- immutable borrow later captured here by closure

还有其他方法可以做到以上几点吗? 我认为克隆初始集合会使我与 World/ecs 脱钩。但即使使用克隆,遍历组件集合也是不可变的借用。

问题是你的 components 向量是一个包含 referencesComponent 的向量,它借鉴了 world,这意味着你可以稍后编辑组件时可变地借用它。

您可以通过几种方式解决此问题:

  • 在创建 compontents 向量时克隆组件。简单,但需要更多分配。
  • 首先不可变地迭代组件并保留更改缓冲区,然后应用这些更改。 CommandBuffer 可以提供帮助 - 您甚至可以将其添加到系统中,legion 将负责创建和刷新。
  • 遍历 Entities,可能使用组件过滤器(IDK,如果它锁定其过滤的存储),并使用 world.entry[_mut] 一次访问一个组件。不需要分配,但性能可能较差。