frederickjjoubert / bevy-ball-game

This is a small game I made to teach the basics of the Bevy Game Engine
https://bevyengine.org
MIT License
78 stars 16 forks source link

Final score race condition (Episode-10) #5

Closed zendril closed 5 months ago

zendril commented 1 year ago

In the Episode-10 branch, sometimes when the enemy hits a player the final score will read:

"Your final score was:" (note, no actual score)

Sometimes it will print out the score.

It seems like by the time the update_final_score_text runs, there may or may not be anything in the mut game_over_event_reader: EventReader<GameOver>,

I'll see if I can pinpoint it and raise a PR, but I'm brand new to Bevy so it may not be immediately evident to me.

zendril commented 1 year ago

The high_scores_updated is always working and I think that is because the system is specified as .add_system(update_score.run_if(in_state(AppState::Game)))

So it will always catch it on the current frame.

By the time the update_final_score_text is running, the frame may have already passed, and the events (if I understand correctly) only live for the duration of the frame.

I believe this is happening because the handle_game_over is reading from the GameOver event, and then during that frame will set app_state_next_state.set(AppState::GameOver);.

It seems like this switch to the GameOver app state is happening a frame later, in which case the GameOver event is gone.. and thus not able to be read by update_final_score_text.

Or that, since things are run in parallel, that every once in a while the update_final_score_text will actually be run because the AppState::GameOver is set AND it is still in the same frame as when the game_over_event_writer.send(GameOver { score: score.value as u32 }); event was sent.

I still don't have a fix, but I believe that is at least somewhat the gist of the issue.

ANKer661 commented 1 year ago

Hi zendril! I met the same problem. I think update_final_score_text can actually capture the event. However, the text_query could have nothing matched.

ANKer661 commented 1 year ago

We can write .add_systems(Update, update_final_score_text), without the run_if() state condition, to ensure update_final_score_text will capture the GameOver event. However, the text_query sometimes can not find the matched entity like this: image image

ANKer661 commented 1 year ago

A possible solution is to get rid of GameOver event, and to use HighScore Resource. Like this: image I test it for several times and it just work fine. Since we use last().unwrap(), we should keep the run_if condition as following: image Or the codes will panic because at first there is nothing in HighScore.

frederickjjoubert commented 9 months ago

Great discussion folks! 😄

frederickjjoubert commented 5 months ago

Fixed by https://github.com/frederickjjoubert/bevy-ball-game/pull/8