-
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
Command execution order does not always match system execution order in the case of ambiguous systems #10122
Description
Bevy version
0.11.2
What you did
I have two systems that take a mutable reference to a resource that represents a document.
The document is essentially a list of spawnable mesh + material pairs.
The code looks something like this:
#[derive(Resource)]
struct MainDocument(Vec<Art>);
struct Art {
entity: Option<Entity>,
mesh: Handle<Mesh>,
material: Handle<StandardMaterial>,
}
fn show_art_system(mut commands: Commands, document: ResMut<MainDocument>) {
// make the art visible using `commands` by spawning entities with the MaterialMeshBundle and store the entity id in the art
}
fn hide_art_system(mut commands: Commands, document: ResMut<MainDocument>) {
// hide the art using `commands` to despawn the entities stored in the art
}What went wrong
Sometimes, the show_art_system will panic with the following error:
error[B0003]: Could not insert a bundle (of type (bevy_pbr::bundle::MaterialMeshBundle<bevy_pbr::pbr_material::StandardMaterial>, bevy_render::view::visibility::NoFrustumCulling)) for entity 19v0 because it doesn't exist in this World.
In my setup, the show_art_system always runs before the hide_art_system,
and the hide_art_system always checks if the Art has an entity to despawn before calling despawn.
When looking at my logs, this is also what I see: the art gets spawned first, and then despawned later.
This panic only happens when the art is spawned and despawned in the same frame.
After a lot of digging, what I discovered is that show_art_system and hide_art_system receive different
Command buffers, and that even though these systems should be synchronized since they request mutable access
to the same resource, sometimes (somewhat rarely) their command buffers will be applied in reverse order relative to the
order in which the systems ran. This leads to the entity being spawned, then the Despawn command is applied to it,
and then the Insert command is applied to it, leading to a panic since the entity was already despawned.
I am not sure if this is a bevy bug or intended behavior.
If this is intended, I would appreciate some direction on how to structure my code to avoid this panic.
Additional information
Sadly, I don't have a simple, consistent way to reproduce this, so I don't have a minimal code example that reproduces the issue.
My actual code that causes this behavior only panics in about ~10% of runs, so it would probably be a bad example, since it also contains a lot of other noise.