I currently spawn the entire scene like this:
commands
.spawn((
SceneRoot(world_assets.level_scene.clone()),
ColliderConstructorHierarchy::new(ColliderConstructor::TrimeshFromMesh),
RigidBody::Static,
WorldEntity,
))
.observe(on_level_spawn);
Then I iterate over spawned entities in an observer to modify or replace them:
fn on_level_spawn(trigger: Trigger<SceneInstanceReady>, children_q: Query<&Children>, mut commands: Commands, name_q: Query<(&Name, &Transform)>, world_assets: Res<WorldAssets>) {
let coin_scene = SceneRoot(world_assets.coin_scene.clone());
for entity in children_q.iter_descendants(trigger.target()) {
if let Ok((name, transform)) = name_q.get(entity) {
match name.as_str() {
n if n.starts_with("coin_spawn") => spawn_coin(transform, &coin_scene, &mut commands),
n if n.starts_with("panel_base") => spawn_random_panel(transform, &mut commands),
_ => {}
}
}
}
}
The problem with this approach is that the entire scene is spawned first, and I patch it afterward. I’d like to avoid this “spawn then despawn/replace” workflow.
Ideally, I want to intercept the GLTF scene instancing process and decide how each node gets spawned (random tile, simplified collider, custom entity, etc.) during the spawn itself.
Pseudocode of what I’m aiming for:
for node in gltf_scene {
match node.name.as_str() {
n if n.starts_with("coin_spawn") => spawn_coin(node.transform),
n if n.starts_with("panel_base") => spawn_random_panel(node.transform),
n if n.starts_with("complex_shape") => spawn_with_simplified_collider(node.transform),
_ => spawn_default_gltf(node),
}
}
Is there a way in Bevy to hook into or override the GLTF scene instantiation so I can control what gets spawned for each node, instead of modifying it after the fact?