Bevy: Despawning causes panics

Created on 12 Aug 2020  路  6Comments  路  Source: bevyengine/bevy

Trying out bevy and started with a player that can shoot bullets. Ran into an issue where spawning more bullets after despawning one causes a panic. Usually need to spawn 2 bullets after one was despawned.
Running on Pop!_OS (basically Ubuntu) with a Ryzen 3700X + GTX TI 1080 and NVIDIA proprietary drivers (version 418.152.00).

Full stacktrace:

thread 'main' panicked at 'no empty slots available in array', /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/nodes/render_resources_node.rs:50:17
stack backtrace:
   0:     0x5576c111ede5 - backtrace::backtrace::libunwind::trace::h75aedf5f78e5147f
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/libunwind.rs:86
   1:     0x5576c111ede5 - backtrace::backtrace::trace_unsynchronized::h18fb73c9ac9ae753
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.46/src/backtrace/mod.rs:66
   2:     0x5576c111ede5 - std::sys_common::backtrace::_print_fmt::h65f97470ff13ec84
                               at src/libstd/sys_common/backtrace.rs:78
   3:     0x5576c111ede5 - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hee061c54ddc9f024
                               at src/libstd/sys_common/backtrace.rs:59
   4:     0x5576c114abdc - core::fmt::write::hfbd2baad61ed21a8
                               at src/libcore/fmt/mod.rs:1117
   5:     0x5576c111af62 - std::io::Write::write_fmt::h72f9bd227f40dc62
                               at src/libstd/io/mod.rs:1508
   6:     0x5576c1121a80 - std::sys_common::backtrace::_print::h2d2cd8fe02feb5fa
                               at src/libstd/sys_common/backtrace.rs:62
   7:     0x5576c1121a80 - std::sys_common::backtrace::print::h801b12991252ba7c
                               at src/libstd/sys_common/backtrace.rs:49
   8:     0x5576c1121a80 - std::panicking::default_hook::{{closure}}::h25fc1fbf3b63b5c8
                               at src/libstd/panicking.rs:198
   9:     0x5576c11217cc - std::panicking::default_hook::h62c897957a5e0f26
                               at src/libstd/panicking.rs:217
  10:     0x5576c11220c3 - std::panicking::rust_panic_with_hook::hb8a276f163c59810
                               at src/libstd/panicking.rs:526
  11:     0x5576c0d0a579 - std::panicking::begin_panic::h0beeb81efb5d4d3e
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/libstd/panicking.rs:456
  12:     0x5576c0be6fef - bevy_render::render_graph::nodes::render_resources_node::BufferArrayStatus::get_or_assign_index::hf492a4e8068393bd
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/nodes/render_resources_node.rs:50
  13:     0x5576c09419d4 - bevy_render::render_graph::nodes::render_resources_node::UniformBufferArrays<T>::setup_uniform_buffer_resources::h23b3ebd594ea1e94
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/nodes/render_resources_node.rs:237
  14:     0x5576c0946324 - bevy_render::render_graph::nodes::render_resources_node::render_resources_node_system::{{closure}}::h069fa2c5b403b0b2
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/nodes/render_resources_node.rs:465
  15:     0x5576bff8eb40 - <bevy_wgpu::renderer::wgpu_render_resource_context::WgpuRenderResourceContext as bevy_render::renderer::render_resource_context::RenderResourceContext>::write_mapped_buffer::h9b86a35a19441905
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_wgpu-0.1.0/src/renderer/wgpu_render_resource_context.rs:521
  16:     0x5576c0945cf2 - bevy_render::render_graph::nodes::render_resources_node::render_resources_node_system::hd89f3a6ec4b76504
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/nodes/render_resources_node.rs:456
  17:     0x5576c0952055 - core::ops::function::Fn::call::h79589152f08ca8eb
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/libcore/ops/function.rs:72
  18:     0x5576c094b9e0 - core::ops::function::impls::<impl core::ops::function::FnMut<A> for &F>::call_mut::h26087de917b9f979
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/libcore/ops/function.rs:253
  19:     0x5576c095fe3e - <Func as bevy_ecs::system::into_system::IntoQuerySystem<(),(Ra,Rb),(A,)>>::system::{{closure}}::he622a81dc394759e
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/system/into_system.rs:218
  20:     0x5576c09616f5 - <bevy_ecs::system::into_system::SystemFn<State,F,ThreadLocalF,Init,SetArchetypeAccess> as bevy_ecs::system::system::System>::run::h80c50a1167514fce
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/system/into_system.rs:61
  21:     0x5576c1011eab - bevy_ecs::schedule::schedule::Schedule::run::hb87ad000ecd04d9c
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/schedule/schedule.rs:138
  22:     0x5576c0b85aee - bevy_render::render_graph::system::render_graph_schedule_executor_system::h2a0d7e2a50852843
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_render-0.1.0/src/render_graph/system.rs:13
  23:     0x5576c0b1c7f1 - core::ops::function::FnMut::call_mut::h4a365c5db4c3016e
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/libcore/ops/function.rs:154
  24:     0x5576c0b7a261 - <F as bevy_ecs::system::into_system::ThreadLocalSystemFn>::run::h9463824cb56a5ccf
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/system/into_system.rs:339
  25:     0x5576c0c0241e - <F as bevy_ecs::system::into_system::IntoThreadLocalSystem>::thread_local_system::{{closure}}::ha71ab17bfba9a2ef
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/system/into_system.rs:315
  26:     0x5576c0bf39dd - <bevy_ecs::system::into_system::SystemFn<State,F,ThreadLocalF,Init,SetArchetypeAccess> as bevy_ecs::system::system::System>::run_thread_local::hdbc9fa8077dbea8e
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/system/into_system.rs:65
  27:     0x5576c1028505 - bevy_ecs::schedule::parallel_executor::ExecutorStage::run::h9786ed11a62fd705
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/schedule/parallel_executor.rs:341
  28:     0x5576c1025fa6 - bevy_ecs::schedule::parallel_executor::ParallelExecutor::run::hf5facd7b347d899c
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_ecs-0.1.0/src/schedule/parallel_executor.rs:59
  29:     0x5576c0ff6d69 - bevy_app::app::App::update::h0315008cd34b2776
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.1.0/src/app.rs:60
  30:     0x5576c0475e27 - bevy_winit::winit_runner::{{closure}}::hcbc86eecf88e0b24
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.1.1/src/lib.rs:140
  31:     0x5576c0458a27 - cart_tmp_winit::platform_impl::platform::sticky_exit_callback::hdcf862bed15c3d24
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/cart-tmp-winit-0.22.2/src/platform_impl/linux/mod.rs:703
  32:     0x5576c04a55b8 - cart_tmp_winit::platform_impl::platform::x11::EventLoop<T>::run_return::hf1c2b05e50990cfe
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/cart-tmp-winit-0.22.2/src/platform_impl/linux/x11/mod.rs:295
  33:     0x5576c04a688e - cart_tmp_winit::platform_impl::platform::x11::EventLoop<T>::run::h6a3136f014c8237b
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/cart-tmp-winit-0.22.2/src/platform_impl/linux/x11/mod.rs:386
  34:     0x5576c045869d - cart_tmp_winit::platform_impl::platform::EventLoop<T>::run::h5659dfb0477b8dd8
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/cart-tmp-winit-0.22.2/src/platform_impl/linux/mod.rs:620
  35:     0x5576c04a0c28 - cart_tmp_winit::event_loop::EventLoop<T>::run::hc16a08826b9d182d
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/cart-tmp-winit-0.22.2/src/event_loop.rs:149
  36:     0x5576c0474f65 - bevy_winit::winit_runner::hf19c3205ee0515e7
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_winit-0.1.1/src/lib.rs:48
  37:     0x5576c04a150f - core::ops::function::Fn::call::haf41d002572a373c
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/libcore/ops/function.rs:72
  38:     0x5576c0fe1e4a - <alloc::boxed::Box<F> as core::ops::function::Fn<A>>::call::ha48473f3ba1c9d15
                               at /rustc/6c8927b0cf80ceee19386026cf9d7fd4fd9d486f/src/liballoc/boxed.rs:1088
  39:     0x5576c0ff6efd - bevy_app::app::App::run::h035f3be4dc4782ee
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.1.0/src/app.rs:73
  40:     0x5576c0ff389b - bevy_app::app_builder::AppBuilder::run::hc9e6a953797c57f1
                               at /home/katis/.cargo/registry/src/github.com-1ecc6299db9ec823/bevy_app-0.1.0/src/app_builder.rs:43
  41:     0x5576bff08560 - my_game::main::h4cdc7192abc0a2c5
                               at src/main.rs:122
  42:     0x5576bfefffbb - std::rt::lang_start::{{closure}}::hf853ee00a16bb423
                               at /home/katis/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67
  43:     0x5576c1122563 - std::rt::lang_start_internal::{{closure}}::hbd178e645b70b347
                               at src/libstd/rt.rs:52
  44:     0x5576c1122563 - std::panicking::try::do_call::hd9e76f93421bce23
                               at src/libstd/panicking.rs:348
  45:     0x5576c1122563 - std::panicking::try::h6776eea046a81bd7
                               at src/libstd/panicking.rs:325
  46:     0x5576c1122563 - std::panic::catch_unwind::hd9dfb4dd4c6fb7d1
                               at src/libstd/panic.rs:394
  47:     0x5576c1122563 - std::rt::lang_start_internal::h47278b515c002423
                               at src/libstd/rt.rs:51
  48:     0x5576bfefff97 - std::rt::lang_start::hfee2c021bf1639f3
                               at /home/katis/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src/libstd/rt.rs:67
  49:     0x5576bff085ba - main
  50:     0x7f31eb3fa0b3 - __libc_start_main
  51:     0x5576bfef9c2e - _start
  52:                0x0 - <unknown>

Process finished with exit code 101

Code:

use bevy::{prelude::*, render::pass::ClearColor};

type Seconds = f64;

struct Player;

struct ShootDelay {
    delay: Seconds,
    last: Seconds,
}

struct Velocity(Vec2);

impl ShootDelay {
    fn can_shoot_next(&self, time: Seconds) -> bool {
        (self.delay + self.last) <= time
    }
}

struct DestroyOutOfBounds;

fn setup(mut commands: Commands, mut materials: ResMut<Assets<ColorMaterial>>) {
    commands
        .spawn(Camera2dComponents::default())
        .spawn(UiCameraComponents::default())
        .spawn(SpriteComponents {
            material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()),
            translation: Translation(Vec3::new(0.0, -250.0, 0.0)),
            sprite: Sprite {
                size: Vec2::new(64.0, 64.0),
            },
            ..Default::default()
        })
        .with(Player)
        .with(ShootDelay {
            delay: 0.3,
            last: 0.,
        });
}

fn input(
    mut commands: Commands,
    mut materials: ResMut<Assets<ColorMaterial>>,
    time: Res<Time>,
    kb: Res<Input<KeyCode>>,
    mouse: Res<Input<MouseButton>>,
    mut query: Query<(&Player, &mut ShootDelay, &mut Translation)>,
) {
    for (_, mut shoot_delay, mut translation) in &mut query.iter() {
        let mut delta_x = 0.0;
        if kb.pressed(KeyCode::A) {
            delta_x -= 1.0;
        }
        if kb.pressed(KeyCode::D) {
            delta_x += 1.0;
        }

        let mut delta_y = 0.0;
        if kb.pressed(KeyCode::W) {
            delta_y += 1.0;
        }
        if kb.pressed(KeyCode::S) {
            delta_y -= 1.0;
        }

        if mouse.just_pressed(MouseButton::Left)
            || (mouse.pressed(MouseButton::Left)
                && shoot_delay.can_shoot_next(time.seconds_since_startup))
        {
            shoot_delay.last = time.seconds_since_startup;
            commands
                .spawn(SpriteComponents {
                    material: materials.add(Color::rgb(0.7, 0.4, 0.3).into()),
                    sprite: Sprite {
                        size: Vec2::new(10., 10.),
                    },
                    translation: Translation(translation.0),
                    ..Default::default()
                })
                .with(Velocity(Vec2::new(0., 200.)))
                .with(DestroyOutOfBounds);
        }

        *translation.0.x_mut() += time.delta_seconds * delta_x * 100.0;
        *translation.0.y_mut() += time.delta_seconds * delta_y * 100.0;
    }
}

fn movement(time: Res<Time>, mut query: Query<(&Velocity, &mut Translation)>) {
    for (velocity, mut translation) in &mut query.iter() {
        *translation.0.x_mut() += time.delta_seconds * velocity.0.x();
        *translation.0.y_mut() += time.delta_seconds * velocity.0.y();
    }
}

fn destroy_out_of_bounds(
    mut commands: Commands,
    windows: Res<Windows>,
    mut query: Query<(&DestroyOutOfBounds, Entity, &mut Translation)>,
) {
    let window = windows.get_primary().unwrap();

    let x_min = -(window.width as f32 / 2.);
    let x_max = window.width as f32 / 2.;

    let y_max = window.height as f32 / 2.;
    let y_min = -(window.height as f32 / 2.);

    for (_, entity, mut translation) in &mut query.iter() {
        if translation.0.x() < x_min
            || translation.0.y() < y_min
            || translation.x() > x_max
            || translation.y() > y_max
        {
            println!("DESTROY ENTITY");
            commands.despawn(entity);
        }
    }
}

fn main() {
    App::build()
        .add_default_plugins()
        .add_resource(ClearColor(Color::rgb(0.7, 0.7, 0.1)))
        .add_startup_system(setup.system())
        .add_system(input.system())
        .add_system(movement.system())
        .add_system(destroy_out_of_bounds.system())
        .run();
}
bug crash ecs

Most helpful comment

Yeah this makes sense to me. Im pretty sure the problem here is the array metadata for gpu-mapped components getting out of sync with the entities. I think we arent handling entity removal correctly in that part of the code.

I'll look into this. Despawning is important :smile:

All 6 comments

Yeah this makes sense to me. Im pretty sure the problem here is the array metadata for gpu-mapped components getting out of sync with the entities. I think we arent handling entity removal correctly in that part of the code.

I'll look into this. Despawning is important :smile:

I've encountered this as well. Here's code that reproduces the issue.

use bevy::prelude::*;

struct DecayerTimer(Timer);

struct Decayer(f32);

fn decayer_system(
  mut commands: Commands,
  time: Res<Time>,
  mut timer: ResMut<DecayerTimer>,
  mut query: Query<(Entity, &mut Decayer)>,
) {
  timer.0.tick(time.delta_seconds);
  if timer.0.finished {
    commands
      .spawn_as_entity(
        Entity::new(),
        SpriteComponents {
          sprite: Sprite {
            size: Vec2::new(50.0, 50.0),
          },
          ..Default::default()
        },
      )
      .with(Decayer(2.0));
    timer.0.reset();
    println!("Spawned a decayer");
  }
  for (entity, mut decayer) in &mut query.iter() {
    decayer.0 -= time.delta_seconds;
    if decayer.0 <= 0.0 {
      commands.despawn(entity);
      println!("Deleted decayer: {:?}", entity);
    }
  }
}

fn init(mut commands: Commands) {
  commands.spawn(Camera2dComponents::default());
}

fn main() {
  App::build()
    .add_default_plugins()
    .add_resource(DecayerTimer(Timer::from_seconds(0.25)))
    .add_startup_system(init.system())
    .add_system(decayer_system.system())
    .run();
}

I'm also getting this error when trying to despawn cubes in a system:
thread 'main' panicked at 'no empty slots available in array' [...]render_graph\nodes\render_resources_node.rs:50:17

It despawns the first one fine, then crashes. In my example I am spawning a cube every second and then despawning them when they move to a specific point. Do I need to free any render resources?

I put together a fairly minimal example here as a gist:
https://gist.github.com/DGriffin91/b592d4ce3ca8ea99204c9ba9a057b74c

I have this issue too. Whenever I change ui screens, I try to despawn the previous entities, but it causes the no empty slots available in array panic.

I'm seeing this issue too. My game spawns objects at the top of the screen and despawns them when they fall to the bottom. These two systems spawn and despawn them:

```rust
fn asteroid_creator_system(
mut commands: Commands,
mut materials: ResMut>,
time: Res

if timer.0.finished {
    println!("spawn asteroid");
    commands
        .spawn(SpriteComponents {
            material: materials.add(Color::rgb(0.2, 0.2, 0.8).into()),
            translation: Translation(Vec3::new(rng.gen_range(-400.0, 400.0), 400.0, 0.0)),
            sprite: Sprite {
                size: Vec2::new(30.0, 30.0),
            },
            ..Default::default()
        })
        .with(Asteroid)
        .with(Gravity);
    timer.0.reset();
}

}

fn asteroid_destroyer_system(
mut commands: Commands,
mut query: Query<(&Asteroid, &mut Translation, Entity)>,
) {
for (_asteroid, translation, entity) in &mut query.iter() {
if translation.0.y() < -400.0 {
commands.despawn(entity);
}
}
}

There is a pr for a fix that worked for me. It hasn't been merged yet, but you can use it by putting this in your cargo.toml
bevy = { git = "https://github.com/Bobox214/bevy.git", branch = "fix_134_135" }
Hopefully it will get merged soon.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

TehPers picture TehPers  路  4Comments

cart picture cart  路  3Comments

ben186 picture ben186  路  5Comments

vultix picture vultix  路  3Comments

Bauxitedev picture Bauxitedev  路  5Comments