如何在loader.load外部访问Three.js加载的GLB/GLTF模型?
解决Three.js中dat.gui无法访问异步加载模型材质的问题
你猜的没错,问题根源就是GLB模型是异步加载的。loader.load()是异步方法,它不会阻塞后续代码执行——也就是说,dat.gui的onChange回调可能在模型加载完成前就被触发,这时model还没被赋值,自然会报"Cannot set properties of undefined"的错误。另外你代码里还有个小问题:model是你赋值的gltf对象,它本身没有material属性,材质在gltf场景下的网格(Mesh)对象里。
解决方法
方法一:等待模型加载完成后再创建GUI控制器
把GUI相关的代码移到loader.load的成功回调里,确保模型加载完成后再绑定控制器:let model const options = { wireframe: false} loader.load('new.glb', function(gltf){ model = gltf scene.add(gltf.scene) // 模型加载完成后再创建GUI控制器 gui.add(options, 'wireframe').onChange(function(e){ // 遍历场景中的所有Mesh,设置wireframe model.scene.traverse(obj => { if(obj.isMesh){ obj.material.wireframe = e } }) }) }, undefined, function (error) { console.error(error) })方法二:在回调中检查模型是否存在,并正确获取材质
如果你需要提前创建GUI控制器,可以在onChange回调里先判断model是否已初始化,同时遍历场景中的网格设置材质:let model const options = { wireframe: false} loader.load('new.glb', function(gltf){ model = gltf scene.add(gltf.scene) }, undefined, function (error) { console.error(error) }) gui.add(options, 'wireframe').onChange(function(e){ // 先检查model是否存在 if(!model) return // 遍历场景中的所有Mesh,设置wireframe model.scene.traverse(obj => { if(obj.isMesh){ obj.material.wireframe = e } }) })
补充说明
GLB模型导出的场景通常是一个THREE.Group,里面可能包含多个Mesh对象,直接访问model.material是错误的。必须用traverse方法遍历场景中的所有对象,筛选出isMesh为true的网格,再设置它们的材质属性。
内容的提问来源于stack exchange,提问作者oldboy
相关产品推荐
相关产品推荐

