Three.js类中存储JSON加载模型问题:无法赋值类变量
解决Three.js异步模型加载无法存入类变量的问题
我一眼就看出问题所在啦——你用的JSONLoader.load是异步操作!当你在createSoldier里直接return obj的时候,模型的加载请求还在后台跑着呢,obj还是初始的null,所以constructor里拿到的this.soldier自然是null,根本加不到场景里。
问题拆解
异步操作的特点就是:代码不会停下来等加载完成,而是继续往下执行。你在constructor里执行this.soldier = this.createSoldier(),紧接着就this.model.add(this.soldier),这时候加载还没完成,this.soldier还是空的,当然没效果。不过模型本身加载正常,是因为加载器确实完成了请求,只是加载完成后创建的模型没被关联到你的类变量和场景里。
解决方案1:用回调函数处理异步结果
修改createSoldier方法,让它接受一个回调函数,当模型加载完成后,再通过回调把模型传递出去:
createSoldier(callback) { const loader2 = new THREE.JSONLoader(); loader2.load('models/untitled.json', (geometry, materials) => { const material = new THREE.MeshBasicMaterial({ color: 0x0000ff }); const obj = new THREE.Mesh(geometry, material); // 加载完成后调用回调,把创建好的模型传回去 callback(obj); }); }
然后在constructor里,调用createSoldier的时候传入回调,在回调里完成变量赋值和添加操作:
constructor(renderer) { super(); this.ground = null; this.model = this.createModel(); this.add(this.model); // 用回调接收加载好的模型 this.createSoldier((soldier) => { this.soldier = soldier; this.model.add(this.soldier); }); }
解决方案2:用Promise+async/await让代码更清晰
如果你觉得回调嵌套看着麻烦,可以把加载逻辑封装成Promise,再用async/await来写:
首先把createSoldier改成返回Promise:
createSoldier() { return new Promise((resolve) => { const loader2 = new THREE.JSONLoader(); loader2.load('models/untitled.json', (geometry, materials) => { const material = new THREE.MeshBasicMaterial({ color: 0x0000ff }); const obj = new THREE.Mesh(geometry, material); resolve(obj); }); }); }
然后给类加一个异步的init方法,在constructor里调用它:
constructor(renderer) { super(); this.ground = null; this.model = this.createModel(); this.add(this.model); // 调用异步初始化方法 this.init(); } async init() { // 等待模型加载完成再赋值 this.soldier = await this.createSoldier(); this.model.add(this.soldier); }
这样写出来的代码更接近同步逻辑,可读性也更好~
内容的提问来源于stack exchange,提问作者user3629376
相关产品推荐
相关产品推荐

