IyesGames / iyes_loopless

Alternatives to Bevy States, FixedTimestep, Run Criteria, that do not use "stage looping" and are composable
Other
249 stars 27 forks source link

"State Transition not found" when adding an enter_system #26

Closed CaioLC closed 2 years ago

CaioLC commented 2 years ago

I have a barebones StatePlugin that crashes whenever I try to add_enter_system(). I saw another opened issue mentioning that the API may have some issue with the Plugin architecture, so I tried moving the add_enter_system to main but did not work either.

this is the error I get:

thread 'main' panicked at 'State Transiton Stage not found (assuming auto-added label)', /{my_directory}/github.com-1ecc6299db9ec823/iyes_loopless-0.6.1/src/state.rs:306:18

Here's a snippet of my main.rs file

fn main() {
    let mut app = App::new();
    app.insert_resource(WindowDescriptor {
        // some not relevant code
    })
    .add_plugins(DefaultPlugins)
    .add_plugin(CameraPlugin)
    .add_plugin(StatePlugin)
    .add_plugin(UiPlugin)
    .add_plugin(GamePlugin);

    app.run();
}

and the StatePlugin file:

use bevy::prelude::*;
use iyes_loopless::prelude::*;

pub const STARTING_GAME_STATE: GameState = GameState::MainMenu;

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum GameState {
    MainMenu,
    Options,
    InGame,
}

pub struct StatePlugin;
impl Plugin for StatePlugin {
    fn build(&self, app: &mut App) {
        app
            .add_loopless_state(STARTING_GAME_STATE)
            .add_system(stage_key_bindings)
            .add_enter_system(&GameState::InGame, setup_game); // adding this line crashes the game
    }
}

// This works fine
fn stage_key_bindings(mut commands: Commands, kb_input: Res<Input<KeyCode>>) {
    if kb_input.just_pressed(KeyCode::Escape) {
        commands.insert_resource(NextState(GameState::MainMenu));
    }
}

// Mockup reset_game function when entering a new game
fn setup_game(mut commands: Commands) {
    dbg!("reset_game!");
    commands.insert_resource(NextState(GameState::InGame));
}

What am I doing wrong? Thanks!

arewerage commented 2 years ago

Try this:

.add_enter_system(GameState::InGame, setup_game);

UPD: Although… You go from the state of InGame to InGame. I don't think that's a good thing…

UPD2: For debugging, I use:

pub struct DebuggingPlugin;

impl Plugin for DebuggingPlugin {
    fn build(&self, app: &mut App) {
        app.add_plugin(FrameTimeDiagnosticsPlugin::default())
            .add_plugin(LogDiagnosticsPlugin::default())
            .add_plugin(WorldInspectorPlugin::default())
            .add_system(bevy::input::system::exit_on_esc_system)
            .add_system(change_game_state.run_if(n_key_just_pressed))
            .add_system(print_current_game_state);
    }
}

fn change_game_state(mut commands: Commands, game_state: Res<CurrentState<GameState>>) {
    match game_state.0 {
        GameState::AssetLoading => {
            commands.insert_resource(NextState(GameState::MainMenu));
        }
        GameState::MainMenu => {
            commands.insert_resource(NextState(GameState::Gameplay));
        }
        GameState::Gameplay => {
            commands.insert_resource(NextState(GameState::AssetLoading));
        }
    }
}

fn n_key_just_pressed(keys: Res<Input<KeyCode>>) -> bool {
    keys.just_pressed(KeyCode::N)
}

fn print_current_game_state(game_state: Res<CurrentState<GameState>>) {
    if game_state.is_changed() {
        println!("Current GameState is {:?}", game_state.0);
    }
}
hankjordan commented 2 years ago

I found that placing .add_loopless_state(X) before I loaded any plugins solved this issue for me.

CaioLC commented 2 years ago

@arewerage thanks. Removing the reference (&) at &GameState::Ingame fixed it.

Your UPD is also correct. "NextState" from InGame to InGame put me in an endless loop, so removed that as well.