Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DynamicScenes contain invalid Entity references #4793

Closed
Azorlogh opened this issue May 18, 2022 · 3 comments · Fixed by #7335
Closed

DynamicScenes contain invalid Entity references #4793

Azorlogh opened this issue May 18, 2022 · 3 comments · Fixed by #7335
Labels
A-Scenes Serialized ECS data stored on the disk C-Bug An unexpected or incorrect behavior

Comments

@Azorlogh
Copy link
Contributor

Azorlogh commented May 18, 2022

Bevy version

Commit hash: 15acd6f (post v0.7.0)

Bug description

Minimal example

use bevy::{ecs::entity::EntityMap, prelude::*};

fn main() {
  App::new()
    .add_plugins(DefaultPlugins)
    .add_startup_system(save_scene_system)
    .run();
}

#[derive(Resource)]
pub struct StoredScene(Option<DynamicScene>);

fn save_scene_system(world: &mut World) {
  let mut scene_world = World::new();

  // Uncomment the following lines to cause the bug!
  let child = scene_world.spawn(()).id();
  scene_world.despawn(child);

  let child = scene_world.spawn(()).id();

  scene_world.spawn(()).push_children(&[child]);

  let type_registry = world.resource::<AppTypeRegistry>();
  let scene = DynamicScene::from_world(&scene_world, type_registry);

  println!("{}", scene.serialize_ron(type_registry).unwrap());

  scene
    .write_to_world(world, &mut EntityMap::default())
    .unwrap();
}

When applying DynamicScenes to a world using write_to_world, the operation will sometimes panic.
(more specifically, it will crash if the DynamicScene was created from any entities with a generation != 0 which belong to a hierarchy)

Cause

DynamicScenes store entities without their generation, which makes sense because the simple ids are transiently unique.

However, Entitys stored in components (such as Parent or Children) still contain the generation.

This means that upon applying the DynamicScene, the mapping phase of write_to_world will try to map the "generationful" Entitys and will fail to find them in the map (because the map only has a 0-generation for its keys).

Important note

OUTDATED
I believe most people never encounter this problem, because DynamicScenes are mainly used alongside serialization, and serialization of an Entity strips it of its generation already. (I didn't find where in the codebase but it's what I deduce)

UPDATE:
The workaround above no longer works as per #6194

Proposed fix

OUTDATED
I believe we would simply need to add a prior mapping phase in DynamicScene::from_world to strip the generation of all Entitys contained in components.
I will file a PR soon. Nevermind, I am not well-enough versed in the deep arts of reflection

UPDATE:
Since the arguments in #6194 are convincing that serializing the generation is useful, I think we need another solution.
Possibly, storing the generation in the DynamicScenes

@Azorlogh Azorlogh added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels May 18, 2022
@Azorlogh Azorlogh changed the title Entities contained in DynamicScene components still contain generation DynamicScenes contain invalid Entity references May 18, 2022
@alice-i-cecile alice-i-cecile added A-Scenes Serialized ECS data stored on the disk and removed S-Needs-Triage This issue needs to be labelled labels May 18, 2022
@Azorlogh
Copy link
Contributor Author

Well, I think my reflection-fu is not strong enough for this, so I'm giving up on the PR, I'll let someone with more experience in that area/more determination tackle this.
I tried implementing the initial generation-stripping mapping phase in DynamicScene::from_world but I don't know how to call MapEntities on the cloned & reflected component. I think doing this might require fiddling with the reflection related types and I'm not too comfortable with that stuff.

@paul-hansen
Copy link
Contributor

I believe most people never encounter this problem, because DynamicScenes are mainly used alongside serialization, and serialization of an Entity strips it of its generation already. (I didn't find where in the codebase but it's what I deduce)

Note that this is no longer the case since #6194. Generation is now serialized so this happens when saving and loading a scene too, making this affect a lot more use cases. Simply saving and loading a scene that contains a dynamic scene with any hierarchy now fails.

@Azorlogh
Copy link
Contributor Author

Azorlogh commented Dec 7, 2022

I updated the original post to reflect this, as well as the minimal repro example 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Scenes Serialized ECS data stored on the disk C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants