Javascript 三个gltf返回未定义
我正在使用GLTF加载程序加载场景中的自定义模型 我有一个classJavascript 三个gltf返回未定义,javascript,promise,three.js,this,gltf,Javascript,Promise,Three.js,This,Gltf,我正在使用GLTF加载程序加载场景中的自定义模型 我有一个classSpaceship.js负责加载模型 //Spaceship.js 从'three/examples/jsm/loaders/GLTFLoader.js'导入{GLTFLoader}; 导出默认类宇宙飞船{ 构造函数(){ this.GLTFLoader=新的GLTFLoader(); this.loadModel(this.GLTFLoader'./spaceship_model.gltf')。然后(结果=>{ this.mo
Spaceship.js
负责加载模型
//Spaceship.js
从'three/examples/jsm/loaders/GLTFLoader.js'导入{GLTFLoader};
导出默认类宇宙飞船{
构造函数(){
this.GLTFLoader=新的GLTFLoader();
this.loadModel(this.GLTFLoader'./spaceship_model.gltf')。然后(结果=>{
this.model=result.scene;
});
}
loadModel(加载器,url){
返回新承诺((解决、拒绝)=>{
装载机(
网址,
gltf=>{
决心(gltf);
},
未定义,
错误=>{
console.error('发生错误',error);
拒绝(错误);
}
);
});
}
}
还有一个类ThreeShell.js
作为整个三个场景的shell
import*作为“三”中的三;
从“./Spaceship.js”导入Spaceship;
导出默认类ThreeShell{
构造函数(容器=document.body){
this.container=容器;
这个.setup();
}
设置(){
...
this.spaceship=新宇宙飞船();
console.log(这是宇宙飞船);
console.log(this.spaceship.model);
...
}
}
不知何故,当记录this.spaceship时,我得到了一个具有model属性的对象。
但是当记录this.spaceship.model
时,我得到了未定义的
我想这可能与承诺有关,目前我对此感到不舒服。这就是我请求您帮助的原因。GLTFLoader异步加载资产
this.spaceship = new Spaceship(); // Loading begins...
console.log(this.spaceship);
// Doesn't yet exist because it gets executed immediately, before loading has completed
console.log(this.spaceship.model);
如果您想访问这个.spaceship.model
,您需要在太空船
课程之外使用承诺
:
this.spaceship = new Spaceship(); // Don't load in constructor...
console.log(this.spaceship);
// Perform load call here
this.spaceship.loadModel().then((result) => {
// Now GLTF will exist here because you're waiting
// for the asynchronous callback
console.log(result.scene);
});
看起来您已经很好地掌握了
Promise
s的工作原理,但是。GLTFLoader异步加载资产
this.spaceship = new Spaceship(); // Loading begins...
console.log(this.spaceship);
// Doesn't yet exist because it gets executed immediately, before loading has completed
console.log(this.spaceship.model);
如果您想访问这个.spaceship.model
,您需要在太空船
课程之外使用承诺
:
this.spaceship = new Spaceship(); // Don't load in constructor...
console.log(this.spaceship);
// Perform load call here
this.spaceship.loadModel().then((result) => {
// Now GLTF will exist here because you're waiting
// for the asynchronous callback
console.log(result.scene);
});
看起来您已经很好地掌握了Promise的工作原理,但是正如Marquizzo所说,该模型异步加载这些行
this.spaceship = new Spaceship();
console.log(this.spaceship.model);
不行。有很多方法可以解决这个问题
另一种方法是添加一个返回加载承诺的等待函数,并使用异步函数等待它
// Spaceship.js
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
export default class Spaceship {
constructor() {
this.GLTFLoader = new GLTFLoader();
this._loadingPromise = this.loadModel(this.GLTFLoader, './spaceship_model.gltf').then(result => {
this.model = result.scene;
});
}
waitForLoad() {
return this._loadingPromise;
}
loadModel(loader, url) {
return new Promise((resolve, reject) => {
loader.load(
url,
gltf => {
resolve(gltf);
},
undefined,
error => {
console.error('An error happened.', error);
reject(error);
}
);
});
}
}
然后在设置中
import * as THREE from 'three';
import Spaceship from './Spaceship.js';
export default class ThreeShell {
constructor(container = document.body) {
this.container = container;
this.setup();
}
async setup() {
...
this.spaceship = new Spaceship();
console.log(this.spaceship);
await this.spaceship.waitForLoad();
console.log(this.spaceship.model);
...
}
}
我并不是说这是好是坏,只是指出有更多的方法,您不必将加载移出构造函数
你也可以这样做
setup() {
...
this.spaceship = new Spaceship();
console.log(this.spaceship);
this.spaceship.waitForLoad().then(() => {
console.log(this.spaceship.model);
});
...
}
正如Marquizzo所说,模型异步加载这些行
this.spaceship = new Spaceship();
console.log(this.spaceship.model);
不行。有很多方法可以解决这个问题
另一种方法是添加一个返回加载承诺的等待函数,并使用异步函数等待它
// Spaceship.js
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
export default class Spaceship {
constructor() {
this.GLTFLoader = new GLTFLoader();
this._loadingPromise = this.loadModel(this.GLTFLoader, './spaceship_model.gltf').then(result => {
this.model = result.scene;
});
}
waitForLoad() {
return this._loadingPromise;
}
loadModel(loader, url) {
return new Promise((resolve, reject) => {
loader.load(
url,
gltf => {
resolve(gltf);
},
undefined,
error => {
console.error('An error happened.', error);
reject(error);
}
);
});
}
}
然后在设置中
import * as THREE from 'three';
import Spaceship from './Spaceship.js';
export default class ThreeShell {
constructor(container = document.body) {
this.container = container;
this.setup();
}
async setup() {
...
this.spaceship = new Spaceship();
console.log(this.spaceship);
await this.spaceship.waitForLoad();
console.log(this.spaceship.model);
...
}
}
我并不是说这是好是坏,只是指出有更多的方法,您不必将加载移出构造函数
你也可以这样做
setup() {
...
this.spaceship = new Spaceship();
console.log(this.spaceship);
this.spaceship.waitForLoad().then(() => {
console.log(this.spaceship.model);
});
...
}
是的,我认为这是一个解决办法。但是我想抽象掉加载程序,这样它就不会妨碍我的主文件。非常感谢。是的,我认为这是一个解决办法。但是我想抽象掉加载程序,这样它就不会妨碍我的主文件。非常感谢。工作起来很有魅力!现在,我知道这只是一个品味的问题,但你会如何进一步把它抽象出来呢?是否无法初始化类并直接获取加载的模型?还是
GLTFLoader
阻止我们这么做?我不知道你在问什么。我当然会把装载机从宇宙飞船上搬走,也会把装载机模型搬出宇宙飞船。它们都没有提到宇宙飞船上的任何东西。尽管您需要等待模型加载,但还是以这种或那种方式。要么通过回调、承诺、异步/等待来实现。这取决于你。如果我不清楚,很抱歉,我是问是否有一种方法可以在类内加载模型,而不必在类外调用方法waitForLoad
。我想这会更有意义,让代码更清晰。所以你会建议让一个新类负责加载一个模型?然后在宇宙飞船内部使用它?若宇宙飞船控制了所有关于模型的信息,那个么就并没有理由访问宇宙飞船外部的模型。宇宙飞船可以加载模型,将其添加到场景中,并对其进行完整处理。我猜这是假设您正在调用spaceshipInstance.update,或者在渲染循环中像一个符咒一样工作!现在,我知道这只是一个品味的问题,但你会如何进一步把它抽象出来呢?是否无法初始化类并直接获取加载的模型?还是GLTFLoader
阻止我们这么做?我不知道你在问什么。我当然会把装载机从宇宙飞船上搬走,也会把装载机模型搬出宇宙飞船。它们都没有提到宇宙飞船上的任何东西。尽管您需要等待模型加载,但还是以这种或那种方式。要么通过回调、承诺、异步/等待来实现。这取决于你。如果我不清楚,很抱歉,我是问是否有一种方法可以在类内加载模型,而不必在类外调用方法waitForLoad
。我想这会更有意义,让代码更清晰。所以你会建议让一个新类负责加载一个模型?然后在宇宙飞船内部使用它?若宇宙飞船控制了所有关于模型的信息,那个么就并没有理由访问宇宙飞船外部的模型。宇宙飞船可以加载模型,将其添加到场景中,并对其进行完整处理。我猜这是假设您正在调用渲染循环中的spaceshipInstance.update
,或者