#Manually flush Commands in the middle of a system without exclusive mutability on the world?
71 messages · Page 1 of 1 (latest)
if not-- I basically know these two systems are going to run serially, one after another-- just for the sake of the flush
is the best way to pass data between two systems like that going to be with Events?
it almost feels like just IO for two normal functions, and i would really like to just do this work in an exclusive system-- but i don't want to lock the entire world
maybe what i'm looking for here is a way to compose systems procedurally without an exclusive ref to World
because doing it declaratively for these things is getting annoying
you cannot mutate the World (apply commands) without a mutable reference to the World, commands can only ever be serial operations
spawning entities, despawning entities, adding components, removing components moves around data that would absolutely be prone to race conditions otherwise
well this is basically what my code looks like right now
so what's going on is
the improvements i'd like to make are: passing current_frame into sync_entities_schedule-- ideally without statefully inserting/removing a resource into the world
is that possible?
one thing i was thinking was using system.run and par_iter
instead of schedules
🤔 if current_frame is stored inside the world, then you can't "pin it" with a reference and also take a mutable reference to the world at the same time
since that would break the "aliasing XOR mutability" rule
current frame is a refcounted serialized snapshot of the world
so it should be fine
there's no active borrow or references to the world
you asked about passing current_frame into sync_entities_schedule, so I assumed you meant as like another input along with &mut World
i mean yeah i kind of just want to provide it as kind of like a local resource to the schedule
or actually sorry-- i want to pass merged_snapshot, which is expensive to build
misspoke
i'm thinking maybe i should just do all this by hand
with par_iter
maybe yeah, sorry I don't understand what you're trying
just want to run these two procedurally instead of building a schedule
first 1 sync_entities_to_world, and then N write_snapshot_to_world_components
write_snapshot_to_world_components in parallel
which should be safe i think?
hmm, I don't think you'll be able to run systems in a procedural way without storing them as entities
actually maybe they don't even have to be systems
spawning and despawning entities and adding and removing components always requires an exclusive lock on the world tho
yeah, queues them up basically
then i guess these don't even have to be systems
since there's going to be an exclusive lock on the world the whole time anyway
yeah, commands are like a database transaction, prepared in advance but not committed until we have a lock
ok actually maybe i will just break this out into normal systems
one exception, when you make a spawn command, you get the Entity value immediately
i like being able to invoke systems procedurally though, it simplifies a ton of code
and especially if a Schedule can do IO, that would be really cool and useful
and have local Resources that don't pollute the whole world
yeah, it's a limit of bevy_ecs
once we implement entity relationships, we can store systems as entities and scheduling constraints as relationships
then you could "procedurally" query systems and run them that way
so another thing is that i planned on making MergedSnapshot zero copy
basically storing a slice of &'a Snapshot
the idea here is that all of your peers send snapshots, and the client merges them
before reading the world state from them
but i don't think this is possible in the ECS at all
which is why i was trying to do it with exclusive systems
does that make sense? not sure how to explain it
right, data stored inside the world has to be T: 'static, cannot store short-lived data in it
there are cases where you can soundly transmute &'a to &'static, as long as you prove/ensure that 'a is functionally equivalent to 'static from the POV of the scope
that makes sense
for example, you can send non-static references from thread A to thread B by transmuting them to 'static, as long as you force A to block until B drops them
hmm
do you think im building this in a fundamentally stupid way
i understand that a lot of this could be resolved "automatically" if i just built a schedule and used resources for everything
that was the old solution, but then i built the zero-copy MergedSnapshot<'a> and went down this road
no, first I'm not 100% clear on what you're doing, and I wouldn't fault you if you do something "weird" since
and ECS go against what people are familiar with
there are things that you can't do in a nice way with bevy because we haven't implemented features yet, or because
makes it challenging
saving and restoring has been a big question for a long time