Changing a Material
When you load a scene from a glTF and spawn it multiple times, the material handles in each instance of the scene point to a shared material asset.
If you want to modify the material properties of only one of these instances, you can clone it, modify it, and add it to the asset server.
Bevy 0.15
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup_scene, setup))
.add_observer(decorate_red_fox)
.run();
}
#[derive(Component)]
struct RedFox;
fn decorate_red_fox(
trigger: Trigger<SceneInstanceReady>,
instances: Query<&SceneInstance, With<RedFox>>,
spawner: Res<SceneSpawner>,
mut material_handles: Query<&mut MeshMaterial3d<StandardMaterial>>,
mut material_assets: ResMut<Assets<StandardMaterial>>,
) {
let Ok(instance) = instances.get(trigger.entity()) else {
return;
};
for instance_entity in spawner.iter_instance_entities(**instance) {
let Ok(mut original_material_handle) =
material_handles.get_mut(instance_entity)
else {
continue;
};
let Some(original_material_asset) =
material_assets.get(&*original_material_handle)
else {
continue;
};
let mut new_material = original_material_asset.clone();
new_material.base_color = basic::RED.into();
*original_material_handle = material_assets.add(new_material).into();
}
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
let fox_handle = asset_server.load("models/animated/Fox.glb#Scene0");
commands.spawn((
SceneRoot(fox_handle.clone()),
Transform::from_scale(Vec3::splat(0.02)).with_translation(Vec3::NEG_X),
RedFox,
));
commands.spawn((
SceneRoot(fox_handle),
Transform::from_scale(Vec3::splat(0.02)).with_translation(Vec3::X),
));
}