如何在Bevy中修改材质属性——调整GLB模型自发光颜色
修改GLTF材质自发光颜色的解决方案
你遇到的问题核心在于:asset_server.load()返回的是Handle<StandardMaterial>——这只是指向材质资源的引用,而非材质对象本身,所以无法直接修改其属性。要修改材质,必须通过Assets<StandardMaterial>资源获取可修改的材质实例,同时还要处理GLTF材质异步加载的特性。
以下是两种可行的实现方案:
方案1:监听材质加载完成后修改原材质
适合需要批量修改原材质、且希望所有引用该材质的实体都生效的场景:
首先定义一个组件用来存储材质句柄,方便后续系统识别并修改:
#[derive(Component)] struct TargetEmissiveMaterial(Handle<StandardMaterial>);
修改你的spawn系统,给每个实体附加这个组件:
fn spawn_main_gltf_scene(mut commands: Commands, asset_server: Res<AssetServer>) { for i in 0..26 { let mesh_path = format!("view_cube/view_cube.glb#Mesh{i}/Primitive0"); let mesh: Handle<Mesh> = asset_server.load(mesh_path); let mat_handle = asset_server.load(format!("view_cube/view_cube.glb#Material{i}")); commands.spawn(( PbrBundle { mesh, material: mat_handle.clone(), ..default() }, RenderLayers::layer(0), PickableBundle::default(), TargetEmissiveMaterial(mat_handle), // 存储材质句柄 )); } }
添加一个专门的系统,监听新添加的TargetEmissiveMaterial组件,等待材质加载完成后修改自发光属性:
fn update_emissive_color( mut materials: ResMut<Assets<StandardMaterial>>, mut query: Query<&TargetEmissiveMaterial, Added<TargetEmissiveMaterial>>, ) { for mat_comp in query.iter() { // 获取可修改的材质实例 if let Some(mut material) = materials.get_mut(&mat_comp.0) { material.emissive = Color::RED; // 可选:调整自发光强度,默认值是0.0 material.emissive_strength = 1.0; } } }
最后在App中注册这两个系统:
fn main() { App::new() .add_plugins(DefaultPlugins) .add_startup_system(spawn_main_gltf_scene) .add_system(update_emissive_color) .run(); }
方案2:克隆材质并创建修改后的副本
适合不需要修改原材质、只想让当前实体使用修改后材质的场景:
这个方案通过LoadedAssets(Bevy 0.10+支持)检查材质是否加载完成,克隆原材质并修改后,将新材质存入资源池再使用:
fn spawn_main_gltf_scene( mut commands: Commands, asset_server: Res<AssetServer>, mut materials: ResMut<Assets<StandardMaterial>>, loaded_materials: Res<LoadedAssets<StandardMaterial>>, ) { for i in 0..26 { let mesh_path = format!("view_cube/view_cube.glb#Mesh{i}/Primitive0"); let mesh: Handle<Mesh> = asset_server.load(mesh_path); let original_mat_handle = asset_server.load(format!("view_cube/view_cube.glb#Material{i}")); // 确保材质已加载完成 if let Some(original_mat) = loaded_materials.get(&original_mat_handle) { // 克隆原材质并修改自发光属性 let mut modified_mat = original_mat.clone(); modified_mat.emissive = Color::RED; modified_mat.emissive_strength = 1.0; // 将修改后的材质存入资源池,得到新的句柄 let modified_mat_handle = materials.add(modified_mat); commands.spawn(( PbrBundle { mesh, material: modified_mat_handle, ..default() }, RenderLayers::layer(0), PickableBundle::default(), )); } } }
关键注意点
- 永远不要直接修改
Handle<T>指向的属性,必须通过Assets<T>资源操作材质实例。 - GLTF资源加载是异步的,必须确保材质加载完成后再执行修改操作,否则
get_mut或loaded_materials.get会返回None。
内容的提问来源于stack exchange,提问作者user6600549
相关产品推荐
相关产品推荐

