bevy/crates
Marco Meijer 2ad27ee4ee
fix: use try_insert instead of insert in bevy_ui to prevent panics when despawning ui nodes (#13000)
# Objective

Sometimes when despawning a ui node in the PostUpdate schedule it
panics. This is because both a despawn command and insert command are
being run on the same entity.

See this example code:

```rs
use bevy::{prelude::*, ui::UiSystem};

#[derive(Resource)]
struct SliceSquare(Handle<Image>);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, create_ui)
        .add_systems(PostUpdate, despawn_nine_slice.after(UiSystem::Layout))
        .run();
}

fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
    commands.spawn(Camera2dBundle::default());
    commands.insert_resource(SliceSquare(asset_server.load("textures/slice_square.png")));
}

fn create_ui(mut commands: Commands, slice_square: Res<SliceSquare>) {
    commands.spawn((
        NodeBundle {
            style: Style {
                width: Val::Px(200.),
                height: Val::Px(200.),
                ..default()
            },
            background_color: Color::WHITE.into(),
            ..default()
        },
        UiImage::new(slice_square.0.clone()),
        ImageScaleMode::Sliced(TextureSlicer {
            border: BorderRect::square(220.),
            center_scale_mode: SliceScaleMode::Stretch,
            sides_scale_mode: SliceScaleMode::Stretch,
            max_corner_scale: 1.,
        }),
    ));
}

fn despawn_nine_slice(mut commands: Commands, mut slices: Query<Entity, With<ImageScaleMode>>) {
    for entity in slices.iter_mut() {
        commands.entity(entity).despawn_recursive();
    }
}
```

This code spawns a UiNode with a sliced image scale mode, and despawns
it in the same frame. The
bevy_ui::texture_slice::compute_slices_on_image_change system tries to
insert the ComputedTextureSlices component on that node, but that entity
is already despawned causing this error:

```md
error[B0003]: Could not insert a bundle (of type `bevy_ui::texture_slice::ComputedTextureSlices`) for entity Entity { index: 2, generation: 3 } because it doesn't 
exist in this World. See: https://bevyengine.org/learn/errors/#b0003
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Encountered a panic when applying buffers for system `bevy_ui::texture_slice::compute_slices_on_image_change`!
Encountered a panic in system `bevy_ecs::schedule::executor::apply_deferred`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
```

Note that you might have to run the code a few times before this error
appears.

## Solution

Use try_insert instead of insert for non critical inserts in the bevy_ui
crate.

## Some notes

In a lot of cases it does not makes much sense to despawn ui nodes after
the layout system has finished. Except maybe if you delete the root ui
node of a tree. I personally encountered this issue in bevy `0.13.2`
with a system that was running before the layout system. And in `0.13.2`
the `compute_slices_on_image_change` system was also running before the
layout system. But now it runs after the layout system. So the only way
that this bug appears now is if you despawn ui nodes after the layout
system. So I am not 100% sure if using try_insert in this system is the
best option. But personally I still think it is better then the program
panicking.

However the `update_children_target_camera` system does still run before
the layout system. So I do think it might still be able to panic when ui
nodes are despawned before the layout system. Though I haven't been able
to verify that.
2024-04-19 18:12:08 +00:00
..
bevy_a11y Set the logo and favicon for all of Bevy's published crates (#12696) 2024-03-25 18:52:50 +00:00
bevy_animation fix find_current_keyframe panic (#12931) 2024-04-13 22:32:21 +00:00
bevy_app Optimize Event Updates (#12936) 2024-04-13 14:11:28 +00:00
bevy_asset Fix a copy-paste typo doc (#13004) 2024-04-17 03:11:56 +00:00
bevy_audio Implement clone for most bundles. (#12993) 2024-04-16 16:37:09 +00:00
bevy_color Fix crates not building individually (#12948) 2024-04-14 00:06:03 +00:00
bevy_core Fix beta lints (#12980) 2024-04-16 02:46:46 +00:00
bevy_core_pipeline Document Camera coordinate space (#13012) 2024-04-18 13:02:15 +00:00
bevy_derive Forbid unsafe in most crates in the engine (#12684) 2024-03-27 03:30:08 +00:00
bevy_dev_tools Fix crates not building individually (#12948) 2024-04-14 00:06:03 +00:00
bevy_diagnostic Refactor App and SubApp internals for better separation (#9202) 2024-03-31 03:16:10 +00:00
bevy_dylib Set the logo and favicon for all of Bevy's published crates (#12696) 2024-03-25 18:52:50 +00:00
bevy_dynamic_plugin Forbid unsafe in most crates in the engine (#12684) 2024-03-27 03:30:08 +00:00
bevy_ecs Fix beta lints (#12980) 2024-04-16 02:46:46 +00:00
bevy_ecs_compile_fail_tests Fix Ci failing over dead code in tests (#12623) 2024-03-21 18:08:47 +00:00
bevy_encase_derive Forbid unsafe in most crates in the engine (#12684) 2024-03-27 03:30:08 +00:00
bevy_gilrs Forbid unsafe in most crates in the engine (#12684) 2024-03-27 03:30:08 +00:00
bevy_gizmos separating finite and infinite 3d planes (#12426) 2024-04-18 14:13:22 +00:00
bevy_gltf Fix crates not building individually (#12948) 2024-04-14 00:06:03 +00:00
bevy_hierarchy fix bevy_hierarchy crate optional feature bevy_app (#12943) 2024-04-13 04:46:00 +00:00
bevy_input Fix beta lints (#12980) 2024-04-16 02:46:46 +00:00
bevy_internal Instrument asset loading and processing. (#12988) 2024-04-16 12:02:11 +00:00
bevy_log Refactor App and SubApp internals for better separation (#9202) 2024-03-31 03:16:10 +00:00
bevy_macro_utils Clean up some low level dependencies (#12858) 2024-04-08 19:45:42 +00:00
bevy_macros_compile_fail_tests Fix Ci failing over dead code in tests (#12623) 2024-03-21 18:08:47 +00:00
bevy_math Math primitives cleanup (#13020) 2024-04-18 23:45:51 +00:00
bevy_mikktspace Enable clippy::ref_as_ptr (#12918) 2024-04-10 20:16:48 +00:00
bevy_pbr Run CheckVisibility after all the other visibility system sets have… (#12962) 2024-04-18 20:33:29 +00:00
bevy_ptr Document the lifetime requirement of byte_offset and byte_add (#12893) 2024-04-08 17:13:35 +00:00
bevy_reflect separating finite and infinite 3d planes (#12426) 2024-04-18 14:13:22 +00:00
bevy_reflect_compile_fail_tests Fix Ci failing over dead code in tests (#12623) 2024-03-21 18:08:47 +00:00
bevy_render Run CheckVisibility after all the other visibility system sets have… (#12962) 2024-04-18 20:33:29 +00:00
bevy_scene Implement clone for most bundles. (#12993) 2024-04-16 16:37:09 +00:00
bevy_sprite Run CheckVisibility after all the other visibility system sets have… (#12962) 2024-04-18 20:33:29 +00:00
bevy_tasks Fix beta CI (#12913) 2024-04-09 17:33:59 +00:00
bevy_text Fix beta lints (#12980) 2024-04-16 02:46:46 +00:00
bevy_time Optimize Event Updates (#12936) 2024-04-13 14:11:28 +00:00
bevy_transform Make Transform::rotate_axis and Transform::rotate_local_axis use Dir3 (#12986) 2024-04-16 13:07:03 +00:00
bevy_ui fix: use try_insert instead of insert in bevy_ui to prevent panics when despawning ui nodes (#13000) 2024-04-19 18:12:08 +00:00
bevy_utils Cleanup the multithreaded executor (#12969) 2024-04-16 02:37:19 +00:00
bevy_window Fix beta lints (#12980) 2024-04-16 02:46:46 +00:00
bevy_winit Fix beta CI (#12913) 2024-04-09 17:33:59 +00:00