bevyengine / bevyengine/bevy

When using DynamicScene to restore the state, StateScoped will not take effect

Open
#17,087 0 comments 0 reactions 0 assignees View on GitHub
A-ECS C-Bug S-Needs-Investigation
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version

v0.15.0

## What you did

When using DynamicScene to restore the state, StateScoped will not take effect. According to the code documentation, when the resources in the dynamic scene exist, the old value should be set to the new value, so in theory, the state transition should be triggered and then the StateScoped effect should be activated, but it is not expected to take effect.

## What went wrong

As expected, when restoring the state through DynamicScene, StateScoped should also be triggered

## Additional information

I made a demo according to the official scene example
KeyS: Save the scene
KeyL: Load the scene
KeyA: Set the state to A
KeyB: Set the state to B

The scene window will show:
Upper left corner: The text of the real state
Lower left corner: Run the text containing StateScoped through OnEnter

Operation:
Use S to save, then B to switch the state, and then L to load the state. The real state has changed, but StateScoped (StateA::A) is not cleared, and OnEnter (StateA::B) is not run.

```rust
use bevy::input::common_conditions::input_just_pressed;
use bevy::{prelude::*, tasks::IoTaskPool};
use std::{fs::File, io::Write};

fn main() {
App::new()
.add_plugins(DefaultPlugins)
.register_type_mutable_state::()
.init_state::()
.enable_state_scoped_entities::()
.add_systems(Startup, setup_camera)
.add_systems(Update, update_real_state)
.add_systems(OnEnter(StateA::A), infotext_a_system)
.add_systems(OnEnter(StateA::B), infotext_b_system)
.add_systems(Update, set_state)
.add_systems(
Update,
save_scene_system.run_if(input_just_pressed(KeyCode::KeyS)),
)
.add_systems(
Update,
load_scene_system.run_if(input_just_pressed(KeyCode::KeyL)),
)
.run();
}

#[derive(States, Reflect, Copy, Clone, Eq, PartialEq, Hash, Debug, Default)]
enum StateA {
#[default]
A,
B,
}

#[derive(Component, Reflect, Debug)]
#[reflect(Component)]
struct RealState;

const SCENE_FILE_PATH: &str = "scenes/test_states.scn.ron";

fn load_scene_system(mut commands: Commands, asset_server: Res) {
commands.spawn(DynamicSceneRoot(asset_server.load(SCENE_FILE_PATH)));
}

fn save_scene_system(world: &mut World) {
let scene = DynamicSceneBuilder::from_world(world)
.deny_all()
.allow_resource::>()
.extract_resources()
.build();

let type_registry = world.resource::();
let type_registry = type_registry.read();
let serialized_scene = scene.serialize(&type_registry).unwrap();

info!("{}", serialized_scene);

#[cfg(not(target_arch = "wasm32"))]
IoTaskPool::get()
.spawn(async move {
// Write the scene RON data to file
File::create(format!("assets/{SCENE_FILE_PATH}"))
.and_then(|mut file| file.write(serialized_scene.as_bytes()))
.expect("Error while writing scene to file");
})
.detach();
}

fn setup_camera(mut commands: Commands, state: Res>) {
commands.spawn(Camera2d);

commands.spawn((
Text::new(format!("Real State {:?}", state.get())),
TextFont {
font_size: 42.0,
..default()
},
Node {
align_self: AlignSelf::FlexStart,
..default()
},
RealState,
));
}

fn update_real_state(mut text: Single<&mut Text, With>, state: Res>) {
text.0 = format!("Real State {:?}", state.get());
}

fn infotext_a_system(mut commands: Commands, state: Res>) {
commands.spawn((
Text::new(format!("Current State {:?}", state.get())),
TextFont {
font_size: 42.0,
..default()
},
Node {
align_self: AlignSelf::FlexEnd,
..default()
},
StateScoped(StateA::A),
));
}

fn infotext_b_system(mut commands: Commands, state: Res>) {
commands.spawn((
Text::new(format!("Show State {:?}", state.get())),
TextFont {
font_size: 42.0,
..default()
},
Node {
align_self: AlignSelf::FlexEnd,
..default()
},
StateScoped(StateA::B),
));
}

fn set_state(input: Res>, mut state: ResMut>) {
if input.just_pressed(KeyCode::KeyA) {
state.set(StateA::A);
}

if input.just_pressed(KeyCode::KeyB) {
state.set(StateA::B);
}
}
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.