bevy
bevy copied to clipboard
UI only visible for one frame when used with animated sprites
Bevy version
0.14.0
[Optional] Relevant system information
System independent.
(Tested on macOS 14.5 M2 and WASM)
What you did
Added UI overlay to gameplay.
What went wrong
UI not visible in gameplay (when 2D sprites are animated).
UI appears for one frame if I resize the window.
The same kind of UI used for the main-menu and pause-menu is working as expected.
Additional information
video recording
https://youtu.be/fPNzRPJ694c
Code: https://github.com/bloodmagesoftware/mageanoid/tree/12ec2d4637218cca65c511161e56116a254b1521
repo: https://github.com/bloodmagesoftware/mageanoid.git
commit: 12ec2d4637218cca65c511161e56116a254b1521
UI is in src/gameplay/hud.rs. Camera is in src/cam.rs.
Update
I added a background and now the UI is rendered as expected.
use bevy::prelude::*;
use crate::gameplay::overlap::StaticObject;
const Z_INDEX: f32 = -100.0;
fn spawn_level(mut commands: Commands, asset_server: Res<AssetServer>) {
let ground = SpriteBundle {
texture: asset_server.load("levels/Untitled/png/Level_0__Ground.png"),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, Z_INDEX)),
..default()
};
let rock = SpriteBundle {
texture: asset_server.load("levels/Untitled/png/Level_0__Rock.png"),
transform: Transform::from_translation(Vec3::new(0.0, 0.0, Z_INDEX + 1.0)),
..default()
};
commands
.spawn((StaticObject, ground))
.with_children(|parent| {
parent.spawn((StaticObject, rock));
});
}
pub struct LdtkPlugin;
impl Plugin for LdtkPlugin {
fn build(&self, app: &mut App) {
app.add_systems(Startup, spawn_level);
}
}
Reproduced half of it:
use bevy::prelude::*;
#[derive(Component)]
struct Behind;
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let health_bar_inner = NodeBundle {
style: Style {
width: Val::Percent(20.0),
height: Val::Percent(20.0),
..default()
},
background_color: Color::srgb(0.8, 0.1, 0.1).into(),
..default()
};
commands.spawn((health_bar_inner, Behind));
}
fn overlap(mut transform_q: Query<&mut Transform, With<Behind>>) {
for mut transform in transform_q.iter_mut() {
transform.translation.z = -transform.translation.y;
}
}
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, overlap);
app.run();
}
The UI disappearing is caused by playing with the UI's z-index. I have no idea why adding a background fixed it, though. Could not reproduce that. I tried putting a sprite behind it, didn't work.
Correction: here's something more minimal:
use bevy::prelude::*;
#[derive(Component)]
struct Behind;
fn setup(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
let health_bar_inner = NodeBundle {
style: Style {
width: Val::Percent(20.0),
height: Val::Percent(20.0),
..default()
},
background_color: Color::srgb(0.8, 0.1, 0.1).into(),
..default()
};
commands.spawn((health_bar_inner, Behind));
}
fn overlap(mut transform_q: Query<&mut Transform, With<Behind>>) {
transform_q.single_mut().translation.z = -1.0;
}
fn main() {
let mut app = App::new();
app.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, overlap);
app.run();
}
To be clear: with background I meant Sprites. In my case, I had one Sprite covering the whole scene. I didn't investigate further because my problem was kind of solved.
It's expected that UI nodes with negative z transforms are not drawn.
Note that the z value of the transform is not the "z index." To control the order your UI nodes drawn in, you want to use ZIndex and/or GlobalZIndex.
Bevy's UI layout system manages the transforms of UI nodes.