You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 04:05:31