bevy
bevy copied to clipboard
Transform not propagated for child due to delay of inserting `Children`
In the following code snippet, the 1.5 scale is not applied to the scene:
fn setup(
mut commands: Commands,
asset_server: Res<AssetServer>,
mut scene_spawner: ResMut<SceneSpawner>,
) {
let scene_holder = commands
.spawn()
.insert(GlobalTransform::default())
.insert(Transform::from_scale(Vec3::splat(1.5)))
.insert(Holder)
.id();
let scene_handle = asset_server.load("models/AlienCake/cakeBirthday.glb#Scene0");
scene_spawner.spawn_as_child(scene_handle, scene_holder);
}
The transform_propagate_system only runs if either the parent is Changed or the child is Changed.
However, in this case the order of operations is
- scene_holder
0v0is spawned (and isChangedfor one frame) - later the scene is spawned (e.g. 0v3)
0v3isChangedfor one frame. AParent(0v0)component is scheduled to be added via commands. parent_update_systemis run, but theinsert Childrencommand is not yet processedtransform_propagate_systemis run.0v3is stillChanged, but since0v0has no children yet nothing happens.- Next frame.
0v0now hasChildren([0v3]). parent_update_systemis run, nothing to be donetransform_propagate_systemis run. This time there are children for0v0, but0v3is not changed anymore, so nothing happens.
The problem is "fixed" by either adding a
fn force_transform_change(mut q: Query<&mut Transform>) {
for mut t in q.iter_mut() { t.deref_mut(); }
}
or removing the Changed from transform_propagate_system.
It is also fixed by adding .with_children(|_| {}) to the scene_holder, because then the parent_update_system can simply insert to the existing children which works without delay.
A simpler repro is here.
The repro can be fixed by using
commands.entity(parent).push_children(&[child]) instead of .insert(Parent(parent)).
Is this still an issue after #4197?
I can confirm this is fixed with #4197, using the repro linked earlier.