Closed msvbg closed 3 weeks ago
It doesn't seem to reproduce with the borders example from the bevy repo at version 0.14.0.
I have seen this occasionally (wild guess: <10% of the time) with one of my projects: https://github.com/rparrett/taipo. It's pretty rare and my attempts at a minimal repro have been unsuccessful so far.
It's encouraging to hear that I'm not the only one with this problem! I peeked through your code but you don't seem to be doing anything too crazy with windowing or cameras. We both spawn the camera in an OnEnter(State)
schedule instead of at Startup
like most examples, which may or may not be something.
That is indeed it! I can reproduce the issue in the borders example with this tiny change:
//! Example demonstrating bordered UI nodes
use bevy::{color::palettes::css::*, prelude::*};
#[derive(States, PartialEq, Eq, Debug, Clone, Hash, Default)]
enum MyState {
#[default]
A,
B,
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.init_state::<MyState>()
.add_systems(Startup, setup)
.add_systems(Update, change_state)
.add_systems(OnEnter(MyState::B), create_camera)
.run();
}
fn change_state(mut state: ResMut<NextState<MyState>>) {
state.set(MyState::B);
}
fn create_camera(mut commands: Commands) {
commands.spawn(Camera2dBundle::default());
}
fn setup(mut commands: Commands) {
let root = commands
.spawn(NodeBundle {
style: Style {
margin: UiRect::all(Val::Px(25.0)),
align_self: AlignSelf::Stretch,
justify_self: JustifySelf::Stretch,
flex_wrap: FlexWrap::Wrap,
justify_content: JustifyContent::FlexStart,
align_items: AlignItems::FlexStart,
align_content: AlignContent::FlexStart,
..Default::default()
},
background_color: Color::srgb(0.25, 0.25, 0.25).into(),
..Default::default()
})
.id();
// labels for the different border edges
let border_labels = [
"None",
"All",
"Left",
"Right",
"Top",
"Bottom",
"Left Right",
"Top Bottom",
"Top Left",
"Bottom Left",
"Top Right",
"Bottom Right",
"Top Bottom Right",
"Top Bottom Left",
"Top Left Right",
"Bottom Left Right",
];
// all the different combinations of border edges
// these correspond to the labels above
let borders = [
UiRect::default(),
UiRect::all(Val::Px(10.)),
UiRect::left(Val::Px(10.)),
UiRect::right(Val::Px(10.)),
UiRect::top(Val::Px(10.)),
UiRect::bottom(Val::Px(10.)),
UiRect::horizontal(Val::Px(10.)),
UiRect::vertical(Val::Px(10.)),
UiRect {
left: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
right: Val::Px(10.),
top: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
top: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
right: Val::Px(10.),
top: Val::Px(10.),
..Default::default()
},
UiRect {
left: Val::Px(10.),
right: Val::Px(10.),
bottom: Val::Px(10.),
..Default::default()
},
];
for (label, border) in border_labels.into_iter().zip(borders) {
let inner_spot = commands
.spawn(NodeBundle {
style: Style {
width: Val::Px(10.),
height: Val::Px(10.),
..Default::default()
},
background_color: YELLOW.into(),
..Default::default()
})
.id();
let border_node = commands
.spawn((
NodeBundle {
style: Style {
width: Val::Px(50.),
height: Val::Px(50.),
border,
margin: UiRect::all(Val::Px(20.)),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..Default::default()
},
background_color: MAROON.into(),
border_color: RED.into(),
..Default::default()
},
Outline {
width: Val::Px(6.),
offset: Val::Px(6.),
color: Color::WHITE,
},
))
.add_child(inner_spot)
.id();
let label_node = commands
.spawn(TextBundle::from_section(
label,
TextStyle {
font_size: 9.0,
..Default::default()
},
))
.id();
let container = commands
.spawn(NodeBundle {
style: Style {
flex_direction: FlexDirection::Column,
align_items: AlignItems::Center,
..Default::default()
},
..Default::default()
})
.push_children(&[border_node, label_node])
.id();
commands.entity(root).add_child(container);
}
}
this is because of https://github.com/bevyengine/bevy/pull/14208 and we want it like thatOnEnter(State)
happens before Startup
after startup, states transitions happens in PreUpdate
, the same schedule where things are being prepared for being usable, which make it a bad candidate to spawn things in, but I'm not sure what it's conflicting with
Can you reproduce this on main? We've resolved all of the non-rendering system order ambiugities, so there's a good chance this was incidentally fixed.
Nope, can't reproduce anymore on latest main. Closing!
Bevy version
0.14.0. This issue was not present in 0.13
[Optional] Relevant system information
I'm using a Retina screen with double scale factor, which is likely to be part of the problem here.
What you did
Started my game.
What went wrong
Sometimes, but not always, my games renders all UI at half the size.
Additional information
This is probably some sort of system ordering issue since it happens inconsistently and infrequently. Unfortunately my game is quite large at this point and it's difficult to break out a minimally reproducible example.