hud state management
Guide for hud state management
HUD State Management
Problem
The game's HUD (Health, Mana, Inventory, etc.) was visible on the Main Menu screen, which is inappropriate. The HUD should only be shown during active gameplay.
Root Cause
The
ui_main_layout system in src/systems/ui/mod.rs was rendering the HUD unconditionally, without checking the current GameState.File:
src/systems/ui/mod.rs (line 226-260)The system had a check for
EditorState but not for GameState:fn ui_main_layout(
// ... parameters ...
editor_state: Option<Res<crate::systems::editor::EditorState>>,
// ... other params ...
) {
// Hide HUD if Editor is Active
if let Some(state) = editor_state {
if state.is_active { return; }
}
// ❌ No check for GameState - HUD renders on Main Menu
// ... render HUD ...
}Solution
Add a
GameState check to conditionally render the HUD only when in GameState::Playing.Code Change
File:
src/systems/ui/mod.rsBefore (lines 246-260):
fn ui_main_layout(
// ... parameters ...
mut coconut_ui_state: ResMut<coconut_stacking_ui::CoconutUIState>,
) {
let ui_assets = params.ui_assets;
// ... unpacking params ...
// Hide HUD if Editor is Active
if let Some(state) = editor_state {
if state.is_active { return; }
}
for event in interaction_reader.read() {
// ... event handling ...
}After (lines 246-264):
fn ui_main_layout(
// ... parameters ...
mut coconut_ui_state: ResMut<coconut_stacking_ui::CoconutUIState>,
game_state: Res<State<crate::GameState>>, // ← Added parameter
) {
let ui_assets = params.ui_assets;
// ... unpacking params ...
// Hide HUD if Editor is Active
if let Some(state) = editor_state {
if state.is_active { return; }
}
// Hide HUD if not in Playing state
if *game_state.get() != crate::GameState::Playing {
return;
}
for event in interaction_reader.read() {
// ... event handling ...
}Why This Works
Bevy's State System: The
State<T> resource tracks the current game state. By adding game_state: Res<State<crate::GameState>> as a system parameter, we can query the current state.Early Return Pattern: If the game is not in
Playing state (e.g., MainMenu, Tutorial, Login), the function returns early before rendering any HUD elements.State Transitions: When the user clicks "New Game" or "Continue" in the main menu, Bevy transitions to
GameState::Playing, and the HUD becomes visible.Verification
After applying the fix:
cargo run --bin legends_clientExpected behavior:
- Main Menu screen shows only the menu UI (no HUD)
- Clicking "New Game" or "Continue" transitions to
GameState::Playing - HUD appears once in the game
Verification Status: ✅ CONFIRMED - HUD is now hidden on the Main Menu.
Related Patterns
Conditional UI Rendering in Bevy
This pattern is common for state-based UI:
fn render_ui_system(
state: Res<State<MyGameState>>,
// ... other params ...
) {
match state.get() {
MyGameState::MainMenu => { /* render menu */ },
MyGameState::Playing => { /* render HUD */ },
MyGameState::Paused => { /* render pause menu */ },
_ => { /* render nothing */ }
}
}Alternative: Run Conditions
Instead of early returns, you can use Bevy's
run_if to conditionally schedule systems:app.add_systems(
Update,
ui_main_layout.run_if(in_state(GameState::Playing))
);Pros:
- System doesn't run at all when not needed (more efficient)
- Cleaner separation of concerns
Cons:
- Requires restructuring the plugin setup
- Less flexible for multi-state UI (e.g., showing some UI in multiple states)
For the current implementation, the early return pattern was chosen because:
- Minimal code change (one line added)
- Preserves existing system structure
- Easy to extend with additional state checks
Files Modified
src/systems/ui/mod.rs(line 248): Addedgame_state: Res<State<crate::GameState>>parametersrc/systems/ui/mod.rs(lines 261-264): AddedGameState::Playingcheck