bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
35.34k stars 3.49k forks source link

entities not present when spawned in the same frame #8515

Closed nablabla closed 6 months ago

nablabla commented 1 year ago

Bevy version = 0.10

What you did

when i add an order using these Sets app.add_system(do_step1.in_set(MySetEnum::Step1)) .add_system(do_step2.in_set(MySetEnum::Step2)) .configure_set(MySetEnum::Step1.before(MySetEnum::Step2)),

If I spawn entities with components in do_step1, they are not found in a query in system do_step2 One step later they are found. but I don't want to check if everything is already there that is tedious and duplicates my code and is dirty since then one step is wasted, i just want to do step2 in the same frame. I went around this by waiting one frame. Which is only dirty.

What you expect

I expect entities from a former systems set to be present in a system set that is executed afterwards

Additional information

i am not sure, is this guy complaining about the same thing? https://github.com/bevyengine/bevy/issues/1613

SkiFire13 commented 1 year ago

As the issue you linked explained this is a very complex feature since Commands can potentially modify anything in the World, and this would conflict with any other system that could potentially be running in parallel with it. The general solution is to put a apply_system_buffers system in between the two system, this way any pending command will be flushed before the second system run and so it will be able to see all the entities.

JoshLambda commented 1 year ago

And there's also an example for apply_system_buffers.

volodalexey commented 1 year ago

And there's also an example for apply_system_buffers.

I faced with the same problem. Thanks!

My solution. I have two systems:

So the final solution I came up with:

use bevy::prelude::{
    apply_system_buffers, App, IntoSystemAppConfig, IntoSystemAppConfigs, IntoSystemConfigs,
    OnEnter, Plugin,
};

pub struct GameOverMenuPlugin;

impl Plugin for GameOverMenuPlugin {
    fn build(&self, app: &mut App) {
        app
            // OnEnter State Systems
            .add_systems(
                (
                    spawn_game_over_menu,
                    apply_system_buffers,
                    update_final_score_text,
                )
                    .chain()
                    .in_schedule(OnEnter(AppState::GameOver)),
            )
  }
}
torsteingrindvik commented 10 months ago

The example is now this: https://github.com/bevyengine/bevy/blob/main/examples/ecs/apply_deferred.rs

@nablabla I think this can be closed since you found your solution and it was not a bug?

nablabla commented 10 months ago

I don't think so, the above workaround is only for startup systems, and also skips a frame. I expect when I explicitly order systems that the second system or the same system can access entities that were created before

torsteingrindvik commented 10 months ago

I just meant that e.g. here: https://github.com/bevyengine/bevy/blob/main/crates/bevy_render/src/lib.rs#L74-L160 apply_deferred is used in a way so that system A and system B will observe entity insertion/removal if one of the Flush sets are in-between.

james7132 commented 6 months ago

With #1613 closed via #9822, this is likely resolved as the second system with the after relationship will now observe any commands produced in its dependency. Closing this out.