Skip to content

Panic when using spawn command within Trigger<OnRemove> observer #15439

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
swejk opened this issue Sep 26, 2024 · 2 comments
Closed

Panic when using spawn command within Trigger<OnRemove> observer #15439

swejk opened this issue Sep 26, 2024 · 2 comments
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior P-Crash A sudden unexpected crash S-Needs-Investigation This issue requires detective work to figure out what's going wrong

Comments

@swejk
Copy link

swejk commented Sep 26, 2024

Bevy version

0.14.2

What you did

Run this code:


#[derive(Component)]
struct TestRemoveComp;

#[derive(Component)]
struct CoundownTimer {
    pub start: Instant,
    pub duration: Duration,
}

#[derive(Component)]
struct TestSpawnComp;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, |mut commands: Commands| {
            commands.spawn((
                TestRemoveComp,
                CoundownTimer {
                    start: Instant::now(),
                    duration: Duration::from_secs_f32(1.),
                },
            ));
        })
        .add_systems(
            Update,
            |mut commands: Commands, query: Query<(Entity, &CoundownTimer)>| {
                for (entity, timer) in &mut query.iter() {
                    if timer.start.elapsed() > timer.duration {
                        commands.entity(entity).despawn();
                    }
                }
            },
        )
        .observe(
            |_: Trigger<OnRemove, TestRemoveComp>, mut commands: Commands| {
                commands.spawn(TestSpawnComp);
            },
        )
        .run();
    }

What went wrong

App panicked.
I am noticing this behaviour only when Commands::spawn is issued within Trigger<OnRemove> observer. Commands::insert and Commands::add works correctly in this context.

thread 'main' panicked at C:\Users\User\.cargo\registry\src\index.crates.io-6f17d22bba15001f\bevy_ecs-0.14.0\src\entity\mod.rs:582:9:
flush() needs to be called before this operation is legal
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `test::main::{{closure}}`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

Additional information

As a workaround I am spawning from dedicated Command instead of spawning directly.

...
 .observe(
            |_: Trigger<OnRemove, TestRemoveComp>, mut commands: Commands| {
                commands.add(TriggerOnRemoveSpawnWorkaround {bundle: TestSpawnComp});
            },
        )

pub struct TriggerOnRemoveSpawnWorkaround<B: Bundle> {
    pub bundle: B,
}

impl <B> Command for TriggerOnRemoveSpawnWorkaround<B> 
where B: Bundle {
    fn apply(self, world: &mut bevy::prelude::World) {
        world.spawn(self.bundle);
    }
}
@swejk swejk added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Sep 26, 2024
@alice-i-cecile alice-i-cecile added A-ECS Entities, components, systems, and events S-Needs-Investigation This issue requires detective work to figure out what's going wrong and removed S-Needs-Triage This issue needs to be labelled labels Sep 26, 2024
@alice-i-cecile
Copy link
Member

Can you reproduce this on main? #15398 and/or #15405 may have fixed this.

@alice-i-cecile alice-i-cecile added the P-Crash A sudden unexpected crash label Sep 26, 2024
@chompaa
Copy link
Member

chompaa commented Sep 28, 2024

I ran the following code on main and the commit before 3d0f240.

Code
use std::time::{Duration, Instant};

use bevy::prelude::*;

#[derive(Component)]
struct TestRemoveComp;

#[derive(Component)]
struct CountdownTimer {
    pub start: Instant,
    pub duration: Duration,
}

#[derive(Component)]
struct TestSpawnComp;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, |mut commands: Commands| {
            commands.spawn((
                TestRemoveComp,
                CountdownTimer {
                    start: Instant::now(),
                    duration: Duration::from_secs_f32(1.),
                },
            ));
        })
        .add_systems(
            Update,
            |mut commands: Commands, query: Query<(Entity, &CountdownTimer)>| {
                for (entity, timer) in &query {
                    if timer.start.elapsed() > timer.duration {
                        commands.entity(entity).despawn();
                    }
                }
            },
        )
        .observe(
            |_: Trigger<OnRemove, TestRemoveComp>, mut commands: Commands| {
                commands.spawn(TestSpawnComp);
            },
        )
        .observe(|_: Trigger<OnAdd, TestRemoveComp>| {
            info!("It works!");
        })
        .run();
}

The panic does not occur on main, but does before 3d0f240, so I believe this to be solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events C-Bug An unexpected or incorrect behavior P-Crash A sudden unexpected crash S-Needs-Investigation This issue requires detective work to figure out what's going wrong
Projects
None yet
Development

No branches or pull requests

4 participants