#System ordering using Sets/Schedules

7 messages · Page 1 of 1 (latest)

left holly
#

I cannot for the life of me understand the differences and usages/applications of States, Sets, and Schedules. (mostly the latter two)

Previously I was using a simple State to manage my system ordering, but I realized that my FixedUpdate time was not being applied to any of my systems, which revealed itself after my computer decided to double its frame processing speed and my game started running at 2x speed lol.

So I set out to create a custom SystemSet which i configured to run in CoreSchedule::FixedUpdate as per @ Alice's recommendation.

However, this broke my asset loading stuff which was using bevy_asset_loader via States. Im not sure what the best way to continue to use this crate to pre-laod all my assets. Can i integrate my game states stuff with my new system set somehow?

The issue seems to be that I have a couple systems that need to run once, like startup systems, but only after my assets have loaded. Previously I used OnEnter(GameState::Main) which worked.

Ive tried something like the following, but without any luck:

.add_systems((
                setup_healthbar_ui
                    .after(ClientPlugin::load_on_start)
                    .run_if(run_once())
                    .in_base_set(CoreSet::PreUpdate),
            ))
            .add_systems(
                (
                    update_healthbar,
                )
                    .in_base_set(CoreGameSet::Main),
            );

I need setup_healthbar_ui to run once before update_healthbar, with a command flush in between.
This is how my custom set is configured

 app.edit_schedule(CoreSchedule::FixedUpdate, |s| {
            s.configure_set(CoreGameSet::Main);
        })
///////
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub enum CoreGameSet {
    Main,
}
left holly
#

based on some more research i think what i need to do is something like:

 app.edit_schedule(CoreSchedule::FixedUpdate, |s| {
    s.configure_set(CoreGameSet::Loading.run_if(in_state(GameState::Loading)));
    s.configure_set(CoreGameSet::Main.run_if(in_state(GameState::Main)));
})
///////
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
#[system_set(base)]
pub enum CoreGameSet {
    Loading,
    Main,
}

However, this satisfies systems that used to run with OnUpdate(GameState::Main) for example, but now OnEnter(GameState::Main). Still not sure how to configure those

stoic dove
#

Yes, you need two states:

In OnEnter(GameState::Loading) you can start loading your assets.

Then have a system running OnUpdate(GameState::Loading) that checks that the assets are loaded, and if so, it sets the NextState to GameState::Main.

setup_healthbar_ui can run in either OnEnter(GameState::Main) or OnExit(GameState::Loading), while update_healthbar can run in OnUpdate(GameState::Main).

The FixedUpdate systems are relevant for movement, changing transforms etc, not "functional" systems like spawning a ui element or updating it on an event etc, imo.

As far as I can tell there's no need to have base sets, but I might be wrong. But what you described at least should be solvable just with states.

left holly
stoic dove
#

do you mean:
app.add_system(my_system.in_set(MySet).in_schedule(OnEnter(GameState::Loading)));
?

left holly
# stoic dove do you mean: `app.add_system(my_system.in_set(MySet).in_schedule(OnEnter(GameSta...

ah i suppose that works yes, I was mostly wondering if its possible to do that at the SystemSet level, such as the code i sent above:

s.configure_set(CoreGameSet::Loading.run_if(in_state(GameState::Loading)));
    s.configure_set(CoreGameSet::Main.run_if(in_state(GameState::Main)));

This code (i think?) allows me to configure a set to run OnUpdate(SomeState), but I cant figure out the equivilant of OnEnter

stoic dove
#

.configure_set add sets to the default schedule, which is CoreSchedule::Main. OnEnter and OnExit have their own schedules automatically added by Bevy when you declare your type that derives States, so as far as I know it doesn't work with .configure_set.

The following should work, for what we discussed, but of course it depends on your use case:

app
  .add_system(load_assets.in_schedule(OnEnter(GameState::Loading)))
  .add_system(go_to_main_state_if_assets_are_loaded.in_set(OnUpdate(GameState::Loading)))
  .add_system(setup_health_bar.in_schedule(OnEnter(GameState::Main)))
  .add_system(update_healthbar.in_set(OnUpdate(GameState::Main)));

Adding systems is already more ergonomic on main and 0.11 will hit soon, so hopefully things will be more clear then.