I am using the Legion ECS and trying to use multiple mutable queries and running into some borrow checker constraints.
I basically want to update the state of components by comparing with all of the other components.
In essence - make components blue if they are adjacent to another component.
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
})
Error with above is 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
Is there another way to do the above? I've thought that cloning the initial collection would decouple me from the World/ecs. But even with a clone, iterating through the component collection is an immutable borrow.
The issue is that your components
vector is a vector containing references to Component
, which borrows from world
and means you can't mutably borrow it later when you go to edit the component.
You can resolve this a couple of ways:
compontents
vector. Easy, but requires more allocation.CommandBuffer
can help with this - you can even add it to a system and legion will take care of creating and flushing.Entities
, possibly with a component filter (IDK if that locks the storage its filtering on), and use world.entry[_mut]
to access components one at a time. Won't require allocation, but might have worse performance.