Panic When Accessing Resource via Context
I'm not entirely sure if I'm doing something wrong here (still pretty new to rust) but I'm getting a panic when trying to pull an initialized resource out of kayak's BevyContext::query_world. If I get rid of all the kayak_ui stuff, the resource is present as expected.
error
Initial seed: 3485847679
creating ui
getting seed from res
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NoSuchResource(NoSuchResource)', ~\
.cargo\git\checkouts\kayak_ui-299a0b6ac8320811\f90c054\kayak_core\src\context.rs:677:71
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\examples\kayak_res_panic.exe` (exit code: 101)
I did my best to try and cut it down to a bare bones reproduction.
cargo.toml
bevy = "0.6.1"
kayak_ui = { git="https://github.com/StarArawn/kayak_ui", rev="f90c0541ea1b8016ccf44904c426ce70e1c9a2aa", features = ["bevy_renderer"] }
rand = "0.8.5"
rand_xoshiro = "0.6.0"
panic.rs
use bevy::prelude::{App as BevyApp, Commands, Res, SystemSet};
use bevy::DefaultPlugins;
use kayak_ui::bevy::BevyKayakUIPlugin;
use kayak_ui::widgets::{App, Text};
use kayak_ui::{
bevy::BevyContext,
core::{render, Index},
};
use rand::Rng;
use rand_xoshiro::{rand_core::SeedableRng, Xoshiro256PlusPlus};
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
enum GameState {
Playing,
}
fn create_ui(mut commands: Commands) {
println!("creating ui");
let context = BevyContext::new(|context| {
println!("getting seed from res");
let seed = context.query_world::<Res<RandomResource>, _, u32>(|c| c.seed);
println!("got seed: {}", seed);
render! {
<App>
<Text content={format!("Seed: {}", seed)} size={12.0} />
</App>
}
});
commands.insert_resource(context);
}
struct RandomResource {
seed: u32,
}
impl Default for RandomResource {
fn default() -> Self {
let mut rng = Xoshiro256PlusPlus::seed_from_u64(1);
let init_seed = rng.gen::<u32>();
println!("Initial seed: {}", init_seed);
RandomResource { seed: init_seed }
}
}
fn main() {
BevyApp::new()
.init_resource::<RandomResource>()
.add_state(GameState::Playing)
.add_plugins(DefaultPlugins)
.add_plugin(BevyKayakUIPlugin)
.add_system_set(SystemSet::on_enter(GameState::Playing).with_system(create_ui))
.run();
}
I tried to make a nearly identical example without kayak that doesn't panic to make sure I wasn't going crazy.
no_panic.rs
use bevy::prelude::*;
use rand::Rng;
use rand_xoshiro::{rand_core::SeedableRng, Xoshiro256PlusPlus};
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
enum GameState {
Playing,
}
fn create_ui(res: Res<RandomResource>) {
println!("getting seed from res");
let seed = res.seed;
println!("got seed: {}", seed);
}
struct RandomResource {
seed: u32,
}
impl Default for RandomResource {
fn default() -> Self {
let mut rng = Xoshiro256PlusPlus::seed_from_u64(1);
let init_seed = rng.gen::<u32>();
println!("Initial seed: {}", init_seed);
RandomResource { seed: init_seed }
}
}
fn main() {
App::new()
.init_resource::<RandomResource>()
.add_state(GameState::Playing)
.add_plugins(DefaultPlugins)
.add_system_set(SystemSet::on_enter(GameState::Playing).with_system(create_ui))
.run();
}
Does it panic if you move that same resource access into a custom widget?
My guess is that we actually don't have access to World at this point.
Seems to be that way. I hadn't yet ventured into custom widgets yet. Building a custom widget that checks world.is_err() as in the full_ui example does not panic.
Hm, yeah it probably is:
https://github.com/StarArawn/kayak_ui/blob/f90c0541ea1b8016ccf44904c426ce70e1c9a2aa/bevy_kayak_ui/src/bevy_context.rs#L40-L49
I think the only way to achieve this unfortunately would be to do so within a widget— where World access is guaranteed— rather than within the constructor function for BevyContext.
This means that we should probably make query_world a pub(crate) access instead of a pub one so other users don't stumble upon the same issue. This should be okay since the only pub access (that I know of) is here:
https://github.com/StarArawn/kayak_ui/blob/f90c0541ea1b8016ccf44904c426ce70e1c9a2aa/bevy_kayak_ui/src/lib.rs#L73-L78
So that will probably need to be dealt with as well (perhaps by just simply moving the process_event system into the update system).
BevyContext::new( wont have access to world here. Another suggestion would be to load in the resource via the create_ui system.
Another suggestion would be to load in the resource via the
create_uisystem.
Actually, yeah this might be a simpler solution assuming you can pass the resource into the closure (which is probably trivial for your RandomResource type since it could implement Copy).
Since solutions to the problem above have been suggested I'm going to close this for now. Feel free to open up a new issue if you feel there is more to do here.