Prefab components creation seem deferred, cannot read/write them on instance on first frame

(Hyper Sonic) #1

I’m trying to instantiate a prefab in the Pong tutorial project by applying https://book.amethyst.rs/stable/prefabs/how_to_define_prefabs_simple.html and imitating examples/prefab_basic. It’s a very dummy prefab that represents the paddle spawn point, it actually starts with a position of (0, 0) so I need to overwrite component values after instantiation. Probably not common in real applications, but I noticed the following:

my prefab component is not ready just after instantiating the prefab in my main game state on_start with:

let instantiated_entity = world.create_entity().with(prefab_handle.clone()).build()

where prefab_handle_clone is a handle to a prefab asset, itself loaded from a RON:

#![enable(implicit_some)]
Prefab(
	entities: [
		PrefabEntity(
			data: SpawnPoint(0.0, 0.0),
		),
	],
)

I noticed it because trying to print all components SpawnPoint:

    world.exec(|spawn_points: ReadStorage<SpawnPoint>| {
        spawn_points.join().for_each(|spawn_point| {
            println!("spawn point: {:?}", spawn_point);
        });
    });

will print nothing, and trying to access SpawnPoint specifically on the instantiated entity:

world.exec(|mut spawn_point_storage: WriteStorage<SpawnPoint>| {
    let spawn_point = spawn_point_storage.get_mut(instantiated_entity).unwrap();
    // overwrite spawn point values here
 });

will panic on unwrap (so the entity exists but there is no component on it yet).

To do exactly like examples/prefab_basic, I printed all SpawnPoint components in the main game state update loop, and this time it showed them, but only at the end of the 2nd frame.

I considered that maybe the prefab asset was still loading, but following the previous chapters of the doc, I created a loading state with progress counter specifically to make sure that all assets were ready when entering the main game state.

By the way, I can read the prefab asset itself so it shows it has been loaded:

let prefab_assets = world.read_resource::<AssetStorage<Prefab<SpawnPoint>>>();
let spawn_point_prefab = prefab_assets
    .get(&paddle_spawn_point_prefab_handle)
    .expect("no spawn point prefab ready");
spawn_point_prefab
    .entities()
    .for_each(|entity| println!("{:?}", entity));

But I’m not able to overwrite the prefab component values on the entity on the go. I’d have to wait for some update later and it’s not too convenient for me as I would need to add some initialized_spawn_point flag not to do it twice.

My questions are:

  • are prefab components creation always deferred?
  • what is the recommended way to overwrite prefab components on instantiation?

I’m not using LazyBuilder, but just in case I tried a world.maintain() after build. It didn’t change anything.

I tried to create an entity with normal components, no prefab, and those are immediately ready.

1 Like
(Duncan Fairbanks) #2

Related issue: https://github.com/amethyst/amethyst/issues/2295

1 Like