bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.17k stars 3.57k forks source link

Panic when lazily adding multiple observers #15370

Closed viridia closed 1 month ago

viridia commented 1 month ago

Bevy version

0.15.0-dev

What you did

I'm creating a vector of observers, and then adding them to the entity. If I add more than one observer this way, I get a panic - but not immediately.

My templating system now has a .observe() method that lets you register an observer. However, this method can't add the observer immediately because the entity doesn't exist yet. Instead, it creates a vector of Observer components:

pub fn observe<E: Event, B2: Bundle, M: Send + Sync + 'static>(
    self,
    observer: impl IntoObserverSystem<E, B2, M> + Sync,
) -> Self {
    self.observers.lock().unwrap().push(Observer::new(observer));
    self
}

Later, when the entity gets created, we add the observers to it:

  for observer in self.observers.lock().unwrap().drain(..) {
      entt.insert(observer.with_entity(display));
  }

This works fine if I call observe() only once for each template node. However, if I want to observe multiple event types, I need to call observe() multiple times. If I do this, the app crashes. However, the crash doesn't happen right away - it happens later, when adding observers to a subsequent entity.

What went wrong

Here's the stack trace:

thread 'main' panicked at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/observer/runner.rs:417:65:
called `Option::unwrap()` on a `None` value
stack backtrace:
   0: rust_begin_unwind
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:74:14
   2: core::panicking::panic
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panicking.rs:148:5
   3: core::option::unwrap_failed
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:2020:5
   4: core::option::Option<T>::unwrap
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/option.rs:970:21
   5: bevy_ecs::observer::runner::hook_on_add::{{closure}}
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/observer/runner.rs:417:65
   6: core::ops::function::FnOnce::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5
   7: bevy_ecs::system::commands::<impl bevy_ecs::world::Command for F>::apply
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/system/commands/mod.rs:1569:9
   8: bevy_ecs::world::command_queue::RawCommandQueue::push::{{closure}}
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/command_queue.rs:182:25
   9: core::ops::function::FnOnce::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:250:5
  10: bevy_ecs::world::command_queue::RawCommandQueue::apply_or_drop_queued::{{closure}}
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/command_queue.rs:272:26
  11: <core::panic::unwind_safe::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/panic/unwind_safe.rs:272:9
  12: std::panicking::try::do_call
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:557:40
  13: std::panicking::try
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panicking.rs:521:19
  14: std::panic::catch_unwind
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/std/src/panic.rs:350:14
  15: bevy_ecs::world::command_queue::RawCommandQueue::apply_or_drop_queued
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/command_queue.rs:265:26
  16: bevy_ecs::world::World::flush_commands
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/mod.rs:2199:17
  17: bevy_ecs::world::World::flush
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/mod.rs:2189:9
  18: bevy_ecs::world::World::spawn_empty
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/mod.rs:916:14
  19: bevy_reactor_signals::cx::Cx::create_entity
             at ./crates/bevy_reactor_signals/src/cx.rs:201:9
  20: <bevy_reactor_obsidian::controls::button::Button as bevy_reactor_views::view_template::ViewTemplate>::create
             at ./crates/bevy_reactor_obsidian/src/controls/button.rs:192:18
  21: <bevy_reactor_views::view_template::ViewTemplateView<VT> as bevy_reactor_views::view::View>::build
             at ./crates/bevy_reactor_views/src/view_template.rs:51:20
  22: <bevy_reactor_views::element::Element<B> as bevy_reactor_views::view::View>::build
             at ./crates/bevy_reactor_views/src/element.rs:165:13
  23: <bevy_reactor_views::element::Element<B> as bevy_reactor_views::view::View>::build
             at ./crates/bevy_reactor_views/src/element.rs:165:13
  24: bevy_reactor_views::build_added_view_roots
             at ./crates/bevy_reactor_views/src/lib.rs:54:9
  25: core::ops::function::FnMut::call_mut
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:166:5
  26: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /rustc/eeb90cda1969383f56a2637cbd3037bdf598841c/library/core/src/ops/function.rs:294:13
  27: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn() .> Out>>::run::call_inner
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/system/exclusive_function_system.rs:229:21
  28: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn() .> Out>>::run
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/system/exclusive_function_system.rs:232:17
  29: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run::{{closure}}
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/system/exclusive_function_system.rs:124:23
  30: bevy_ecs::world::World::last_change_tick_scope
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/world/mod.rs:2366:9
  31: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run
             at /Users/talin/.cargo/git/checkouts/bevy-f7ffde730c324c74/179c2e1/crates/bevy_ecs/src/system/exclusive_function_system.rs:116:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_reactor_views::build_added_view_roots`!
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
alice-i-cecile commented 1 month ago

Can you link to the line that's panicking for others to quickly check it out?

viridia commented 1 month ago

Actually, I figured it out, I was spawning the observers incorrectly.