bevyengine / bevy

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

Running the same system in two different states is treated as ambiguous by the scheduler #14335

Open dothanhtrung opened 1 month ago

dothanhtrung commented 1 month ago

Sorry. I am not sure if this is a bug or it is expected as design.

Bevy version

0.14

Relevant system information

Cargo version 1.79.0 (ffa9cf99a 2024-06-03)
Rust 1.79.0 (129f3b996 2024-06-10)
OS Fedora 40

What you did

I added a same system to two different states but the app cannot run.

use bevy::prelude::*;

#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, States)]
enum GameState {
    #[default]
    Menu,
    Ingame,
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_state::<GameState>()
        .add_systems(Update, (a, b.after(a)).run_if(in_state(GameState::Menu)))
        .add_systems(Update, a.run_if(in_state(GameState::Ingame)))
        .run();
}

fn a() {
    println!("a");
}
fn b() {
    println!("b");
}

What went wrong

Additional information

If I add system a into only one state, application can run:

This is okay:

    App::new()
        .add_plugins(DefaultPlugins)
        .init_state::<GameState>()
        .add_systems(Update, (a, b.after(a)).run_if(in_state(GameState::Menu)))  // a() is in only one state
        .run();

This is okay:

    App::new()
        .add_plugins(DefaultPlugins)
        .init_state::<GameState>()
        .add_systems(Update, a.run_if(in_state(GameState::Ingame)))   // a() is in only one state
        .run();

I know I can use (a, b).chain() instead, but somtimes using after() is cleaner.

Full error logs

2024-07-15T14:18:37.520684Z  INFO bevy_render::renderer: AdapterInfo { name: "AMD Radeon RX 6700 XT (RADV NAVI22)", vendor: 4098, device: 29663, device_type: DiscreteGpu, driver: "radv", driver_info: "Mesa 24.1.2", backend: Vulkan }
2024-07-15T14:18:37.715868Z  INFO bevy_winit::system: Creating new window "App" (Entity { index: 0, generation: 1 })
thread 'main' panicked at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/schedule/schedule.rs:383:33:
Error when initializing schedule Update: Tried to order against `SystemTypeSet(fn FunctionSystem<fn(), a>())` in a schedule that has more than one `SystemTypeSet(fn FunctionSystem<fn(), a>())` instance. `SystemTypeSet(fn FunctionSystem<fn(), a>())` is a `SystemTypeSet` and cannot be used for ordering if ambiguous. Use a different set without this restriction.
stack backtrace:
   0: rust_begin_unwind
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/std/src/panicking.rs:652:5
   1: core::panicking::panic_fmt
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/panicking.rs:72:14
   2: bevy_ecs::schedule::schedule::Schedule::run::{{closure}}
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/schedule/schedule.rs:383:33
   3: core::result::Result<T,E>::unwrap_or_else
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/result.rs:1431:23
   4: bevy_ecs::schedule::schedule::Schedule::run
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/schedule/schedule.rs:382:9
   5: bevy_ecs::world::World::try_run_schedule::{{closure}}
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/world/mod.rs:2743:55
   6: bevy_ecs::world::World::try_schedule_scope
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/world/mod.rs:2676:21
   7: bevy_ecs::world::World::try_run_schedule
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/world/mod.rs:2743:9
   8: bevy_app::main_schedule::Main::run_main::{{closure}}
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.14.0/src/main_schedule.rs:227:25
   9: bevy_ecs::world::World::resource_scope
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/world/mod.rs:1886:22
  10: bevy_app::main_schedule::Main::run_main
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.14.0/src/main_schedule.rs:225:9
  11: core::ops::function::FnMut::call_mut
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:166:5
  12: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /rustc/129f3b9964af4d4a709d1383930ade12dfe7c081/library/core/src/ops/function.rs:294:13
  13: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run::call_inner
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/system/exclusive_function_system.rs:218:21
  14: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0) .> Out>>::run
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/system/exclusive_function_system.rs:221:17
  15: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run::{{closure}}
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/system/exclusive_function_system.rs:111:23
  16: bevy_ecs::world::World::last_change_tick_scope
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/world/mod.rs:2215:9
  17: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run
             at /home/kimtinh/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.14.0/src/system/exclusive_function_system.rs:103:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!

Process finished with exit code 101
alice-i-cecile commented 1 month ago

In theory we could statically determine that the run conditions are mutually exclusive 🤔 That would be very hard, and I'm not sure it's worth it, but maybe it is for states? Not sure.

The other workaround is to use a named system set and order relative to that.