#Help with understanding reflect, serialization and deserialization

12 messages · Page 1 of 1 (latest)

white crown
#

I am working on project where i want to create some sort of prefab system for spawning objects.
I my game i want that each Entity has EntityId, path to model, size(Vec3) and some random components specific to each object(Entity).

// wall.ron
(
    id: EntityId("base:wall"),
    path: "assets/models/wall.gltf#Scene0",
    size: (
        x: 1.0,
        y: 2.0,
        z: 1.0,
    ),
    components: [
        ComponentA(
            val_a: 42.0,
            val_b: None,
        ),
        ComponentB(
            val: 10,
            val_max: 10,
        ),
    ],
)

On spawning prefab each entity also get inserted transform, scene root for model and collider cube with size.
Then i would like to save scene as level.
In gameplay i need to load that, during gameplay component values might change, then i want to save level. And when i load it back it must stays the same.

harsh shuttle
#

Loading is just asset_server.load

white crown
#

ok
i am now trying this
prefab:

// wall.scn.ron
(
  resources: {},
  entities: {
    4294967297: (
      components: {
        "scene_dynamic::data::EntityId": ("base:wall"),
        "scene_dynamic::data::ModelPath": ("assets/models/wall.gltf#Scene0"),
        "scene_dynamic::save::Saveable": (),
        "scene_dynamic::new_pack::ComponentA": (
            x: 42.0,
            maybe_bool: None,
        ),
        "scene_dynamic::new_pack::Size": (
            s: (1.0, 2.0, 1.0),
        ),
      },
    ),
  },
)

and i can add system that will add collider:

fn add_colliders_to_prefabs(mut commands: Commands, query: Query<(Entity, &Size), Added<Size>>) {
    for (entity, size) in &query {
        commands.entity(entity).insert(Collider { s: size.s });
    }
}
#

is there better way of defining only prefab (only components) or do i need to define whole scene (resources,entities) as i wrote above?

harsh shuttle
#

The scene can be as big or as small as you like

#

Query with Added has some overhead, try an observer instead

white crown
#

ok will try

white crown
#
pub fn spawn(
        &self,
        id: &EntityId,
        commands: &mut Commands,
        position: Vec3,
        rotation_y: f32,
    ) -> Entity {
        let scene_handle = self
            .scenes
            .get(id)
            .unwrap_or_else(|| panic!("Entity '{}' not registered in EntityRegistry", id.0));

        commands
            .spawn((
                DynamicParent,
                DynamicSceneRoot(scene_handle.clone()),
                Transform::from_translation(position)
                    .with_rotation(Quat::from_rotation_y(rotation_y)),
            ))
            .id()
    }

i spawn correct thing but it spawns in hierarchy. So spawned entity is parent of my prefab that i want.
Because later i do this and marker is not on my actual prefab.

let e = entity_registry.spawn(&s.entity_id, &mut commands, s.position, s.rotation);
commands.entity(e).insert(Preview { valid: true });

But if i make system that removes this parent:

fn remove_parent_from_child(
    mut commands: Commands,
    query: Query<(Entity, &Children), (With<DynamicParent>, Added<Children>)>,
) {
    for (parent_entity, children) in &query {
        if let Some(&child) = children.first() {
            commands.entity(child).remove_parent_in_place();
            commands.entity(parent_entity).despawn();
        }
    }
}

Then i lose Preview marker that i need.
So my question is can i spawn file.scn.ron and i get prefab/entity directly not as child of parent

harsh shuttle
white crown
#

if i use SceneSpawner then i can't add Transform component to it because it is scene not entity.
Then if i try to get entity from scene it fails because scene is not spawned yet

let instance_id = scene_spawner.spawn_dynamic(scene_handle.clone());
        if let Some(entity) = scene_spawner.iter_instance_entities(instance_id).next() {
            commands.entity(entity).insert(
                Transform::from_translation(position)
                    .with_rotation(Quat::from_rotation_y(rotation_y)),
            );
            return entity;
        }
        panic!("No enitties in scene");

Now i am questioning if i should use DynamicScene.

harsh shuttle
#

you can create an observer for SceneInstanceReady and add the transform there, you would just need to create a mapping for loading scene instance and the Transform they should have