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

如何访问three.js中必须声明在函数内部的OBJ模型对象

问题根因

这不是变量作用域导致的访问失败,本质是异步资源加载的时序问题:
页面初始化后animate渲染循环就会逐帧执行,但MTL、OBJ资源的网络加载需要耗时,加载完成前你在外部声明的house变量值始终为undefined,此时直接读取house.position属性就会抛出类型错误,和你预声明变量的写法没有关系。

可直接落地的解决方法

方法1:动画循环内增加空值判断(零成本适配现有代码)

不需要重构现有加载逻辑,只需要在操作house对象前先判断它是否已经完成加载赋值,等模型加载完成后再执行位移逻辑即可。
修改后的animate函数代码如下:

function animate(){
    // 模型加载完成、house被赋值后才执行位移
    if(house){
        house.position.x += 0.01; // 步长建议调小,否则模型移动速度过快直接飞出视野
    }
    renderer.render(scene,camera);
    sLightHelper.update();
}

这个写法改动最小,完全适配你当前的代码结构,是单模型场景下最常用的处理方式。

方法2:封装加载Promise,等模型就绪后再启动渲染循环(结构更清晰)

如果不想在渲染循环里加判断,可以把MTL+OBJ的串联加载逻辑封装为Promise,等模型加载完成、house变量完成赋值后,再启动渲染循环,从流程上避免访问到未初始化的对象。
核心实现代码:

// 封装模型加载方法
function loadHouse() {
    return new Promise((resolve, reject) => {
        const mtlLoader = new MTLLoader();
        mtlLoader.load(
            '../source/MaryStanfordLifeboatHouse02.mtl',
            (materials)=>{
                materials.preload();
                const objLoader = new OBJLoader()
                objLoader.setMaterials(materials)
                objLoader.load(
                    '../source/MaryStanfordLifeboatHouse02.obj',
                    (object)=>{
                        scene.add(object);
                        object.rotation.x = 1/2 * Math.PI;
                        object.rotation.y =  Math.PI;
                        resolve(object);
                    },
                    undefined,
                    (err)=>reject(err)
                )
            },
            undefined,
            (err)=>reject(err)
        )
    })
}

let house = null;
// 等模型加载完成后再启动渲染循环
loadHouse().then(model => {
    house = model;
    renderer.setAnimationLoop(animate);
})

function animate(){
    // 启动循环时house必然已完成赋值,不需要额外判断
    house.position.x += 0.01;
    renderer.render(scene,camera);
    sLightHelper.update();
}
注意事项
  • 不要把所有动画、交互逻辑全部堆在OBJ加载的回调函数内部,后续如果新增多模型加载、GUI控制等逻辑,代码可维护性会极差
  • 位移步长不要设置为1,Three.js默认单位为1米,每帧移动1米会导致模型瞬间移出视野,建议根据实际效果在0.01~0.1区间调整
  • 现有代码中材质加载失败的日志存在拼写错误,Material Eror可修正为Material Error,不影响运行但方便后续排查加载问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 11:21:29