三次gltf返回未定义

问题描述 投票:0回答:2

我正在使用GLTF加载程序在我的场景中加载自定义模型。

我有一个负责加载模型的Spaceship.js类。

// Spaceship.js

import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';

export default class Spaceship {
  constructor() {
    this.GLTFLoader = new GLTFLoader();

    this.loadModel(this.GLTFLoader, './spaceship_model.gltf').then(result => {
      this.model = result.scene;
    });
  }

  loadModel(loader, url) {
    return new Promise((resolve, reject) => {
      loader.load(
        url,

        gltf => {
          resolve(gltf);
        },

        undefined,

        error => {
          console.error('An error happened.', error);
          reject(error);
        }
      );
    });
  }
}

以及用作整个三个场景的外壳的类ThreeShell.js

import * as THREE from 'three';
import Spaceship from './Spaceship.js';

export default class ThreeShell {
  constructor(container = document.body) {
    this.container = container;
    this.setup();
  }

  setup() {
    ...

    this.spaceship = new Spaceship();
    console.log(this.spaceship);
    console.log(this.spaceship.model);

    ...
  }
}

以某种方式,当登录this.spaceship时,我得到一个具有model属性的对象。但是当登录this.spaceship.model时,我得到的是undefined

enter image description here

我想这可能与诺言有关,我目前对此不太满意。这就是为什么我要您的帮助。

javascript promise three.js this gltf
2个回答
1
投票

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);

如果要访问this.spaceship.model,则需要从Promise类的外部使用Spaceship

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的工作原理,但是here's a bit of further clarification


0
投票

正如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);
    });

    ...
  }
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.