bevyengine / bevyengine/bevy

Command execution order does not always match system execution order in the case of ambiguous systems

Open
#10,122 11 comments 0 reactions 0 assignees View on GitHub
A-ECS C-Bug
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

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:
```rust
#[derive(Resource)]
struct MainDocument(Vec);

struct Art {
entity: Option,
mesh: Handle,
material: Handle,
}

fn show_art_system(mut commands: Commands, document: ResMut) {
// 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) {
// 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_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.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.