Skip to content

Done component added inside observer with OnAdd a state are never read by done() trigger #24

Description

@scorsi

Hi,

Title self-explanatory about the bug.

Here's a 100% repro:

use bevy::prelude::*;
use seldom_state::prelude::*;

fn main() {
    App::new()
        .add_plugins((DefaultPlugins, StateMachinePlugin::default()))
        .add_systems(Startup, startup)
        .add_observer(observer)
        .run();
}

#[derive(Component, Copy, Clone)]
struct Init;

#[derive(Component, Copy, Clone)]
struct Ready;

#[derive(Component, Copy, Clone)]
struct Working;

#[derive(Component, Copy, Clone)]
struct NotWorking;

fn startup(mut commands: Commands) {
    commands.spawn((
        StateMachine::default()
            .trans::<Init, _>(
                move |In(_): In<Entity>, time: Res<Time>| {
                    if time.elapsed_secs() >= 5.0 { // In order to repro the bug, the state should be added later not instant
                        Ok(())
                    } else {
                        Err(())
                    }
                },
                Ready,
            )
            .trans::<Ready, _>(done(Some(Done::Success)), Working)
            .trans::<Ready, _>(done(Some(Done::Failure)), NotWorking)
            .set_trans_logging(true),
        Init,
    ));
}

fn observer(trigger: Trigger<OnAdd, Ready>, mut commands: Commands) {
    dbg!("add Done::Success");
    commands.entity(trigger.target()).insert(Done::Success);
}
2025-07-05T18:56:31.110834Z  INFO bevy_winit::system: Creating new window App (0v1)
[src\main.rs:45:5] "add Done::Success" = "add Done::Success"
2025-07-05T18:56:36.176137Z  INFO seldom_state::machine: 8v1#4294967304 transitioned from bug_repro::Init to bug_repro::Ready
2025-07-05T18:56:41.420285Z  INFO bevy_window::system: No windows are open, exiting    
2025-07-05T18:56:41.421504Z  INFO bevy_winit::system: Closing window 0v1

It seems that the Done is added before the StateMachine see the transition and thus get cleaned before being read by the correct trigger... and so I soft-lock the game.
Do you have any ideas?

(I managed it with my own components for Done/Failure and own cleanup mechanism, so that's not an urgent matter)

Thanks,

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions