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

Three.js修改GLTF模型Body材质后对应部位动画失效问题

问题根因

带骨骼/变形动画的GLB模型加载时,GLTFLoader会自动给对应网格的材质开启动画渲染必需的参数:

  • 对蒙皮网格(SkinnedMesh)自动设置材质skinning = true,支持GPU骨骼变换计算
  • 对带变形目标的网格自动设置morphTargets/morphNormals = true,支持形变动画计算

你当前代码直接给Body网格替换了全新创建的MeshStandardMaterial实例,新材质默认上述动画参数全为关闭状态,动画变换数据无法传入渲染管线,最终导致Body部位不响应动画变为静态,其余未替换材质的网格不受影响,可正常播放动画。
另外你代码里的类型判断用instanceof THREE.Mesh存在兼容风险,不同模块引入Three.js时可能出现类实例不匹配的问题,推荐用Three.js内置的isMesh/isSkinnedMesh属性做判断。

修复方案

方案一(推荐):不替换材质实例,直接修改原材质属性

这种方式可以完整保留GLTFLoader预配置的所有动画、渲染相关参数,不会引发动画异常,仅修改你需要的颜色、线框属性即可:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
const gltfLoader = new GLTFLoader()

let mixer = null;

gltfLoader.load(
'models/bot/model.glb',
(gltf) => {
    gltf.scene.traverse((child) => {
        // 用内置属性判断网格,兼容性更好
        if(child.isMesh && child.name === 'Body'){
            // 直接修改原有材质属性
            child.material.color.set('red');
            child.material.wireframe = true;
        }
    })

    mixer = new THREE.AnimationMixer(gltf.scene);
    const action = mixer.clipAction(gltf.animations[1])
    action.play()
    scene.add(gltf.scene)
}
)

方案二:必须替换全新材质时,补全动画相关参数

如果因为业务需求必须替换为全新的材质实例,创建材质时要根据网格类型手动开启对应的动画支持参数:

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
const gltfLoader = new GLTFLoader()

let mixer = null;

gltfLoader.load(
'models/bot/model.glb',
(gltf) => {
    gltf.scene.traverse((child) => {
        if(child.isMesh && child.name === 'Body'){
            child.material =  new THREE.MeshStandardMaterial({
                color: 'red',
                wireframe: true,
                // 蒙皮网格开启动画支持
                skinning: child.isSkinnedMesh,
                // 带变形目标的网格开启动画支持
                morphTargets: !!child.morphTargetInfluences?.length,
                morphNormals: !!child.morphTargetDictionary
            });
        }
    })

    mixer = new THREE.AnimationMixer(gltf.scene);
    const action = mixer.clipAction(gltf.animations[1])
    action.play()
    scene.add(gltf.scene)
}
)
补充说明
  • 你原代码里写的child.material.needsUpdate = true在这个场景下不需要手动添加,修改材质颜色、wireframe属性时Three.js会自动标记材质更新,手动强制设置反而可能在部分版本下引发不必要的材质重编译开销。
  • 你写的动画循环部分逻辑没有问题,不需要修改。

内容的提问来源于stack exchange,提问作者Urooook

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:48:14