javascript - three.js 如何确保在加载模型后加载其他 javascript 文件
问题描述
所以我有一个调用负载管理器和场景管理器的 main.js。
//Load Manager
import { LoadManager } from './sceneSubjects/LoadManager.js';
//Scene Manager
import { SceneManager } from './SceneManager.js'
//Load manager
const loadmn = new LoadManager();
//Scene Manager
const canvas = document.getElementById("canvas");
const sceneManager = new SceneManager(canvas, loadmn);
bindEventListeners();
render();
function bindEventListeners() {
window.onresize = resizeCanvas;
resizeCanvas();
}
function resizeCanvas() {
canvas.style.width = '100%';
canvas.style.height = '100%';
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
sceneManager.onWindowResize();
}
function render() {
requestAnimationFrame(render);
sceneManager.update();
}
在负载管理器内部
没有什么特别的功能只是加载 2 个模型一个玩家模型和一个敌人模型
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
//
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/loaders/GLTFLoader.js';
export class LoadManager {
constructor() {
console.log("hey hey LoadManager");
//Load manager
const loadingpage = document.getElementById('loading-screen');
this.loadManager = new THREE.LoadingManager();
this.loadManager.onProgress = function (item, loaded, total) {//display progress when loading
// console.log('Loading file: ' + item, '.\n Loaded ' + loaded + ' of ' + total + ' files.');
document.getElementById("loadingMessage").innerHTML = 'Loading file: ' + item;
console.log('Loading file: ' + '.\n Loaded ' + loaded + ' of ' + total + ' files.');
// document.getElementById("loadingMessage").innerHTML = loaded + ' of ' + total + ' files.';
};
this.loadManager.onError = function (item) {//display error when loading erroe appears
console.log('There was an error loading ' + item);
document.getElementById("loadingMessage").innerHTML = 'There was an error loading : ' + item;
}
this.loadManager.onLoad = function () {//loading complete
console.log('Loading complete!');
document.getElementById("loadingMessage").innerHTML = 'Loading complete!';
loadingpage.style.display = 'none';
};
this.playerModel = null;
this.enemyModel = null;
//load the player and enemy ships
const loader = new GLTFLoader(this.loadManager);
loader.load(~~~
this.playerModel = gltf.scene;
console.log(" player model loaded");
});
loader.load(~~~
this.enemyModel = gltf.scene;
console.log(" enemy model loaded");
});
}
get getPlayerModel() {
return this.playerModel;
}
get getEnemyModel() {
return this.enemyModel;
}
}
在场景管理器里面
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.118/build/three.module.js';
import * as YUKA from './libs/yuka.module.js';
//loader
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/loaders/GLTFLoader.js';
//effect
import { EffectComposer } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/postprocessing/EffectComposer.js';
import { RenderPass } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/postprocessing/RenderPass.js';
import { ShaderPass } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/postprocessing/ShaderPass.js';
import { UnrealBloomPass } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/postprocessing/UnrealBloomPass.js';
import { GlitchPass } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/postprocessing/GlitchPass.js';
//lock the mouse pointer while in game
import { PointerLockControls } from 'https://cdn.jsdelivr.net/npm/three@0.118/examples/jsm/controls/PointerLockControls.js';
//scene subjects
import { Player } from './sceneSubjects/Player.js';
import { Enemy } from './sceneSubjects/enemy.js';
import { EnemyBehaviour } from './sceneSubjects/enemyBehaviour.js';
import { World } from './sceneSubjects/world.js'
export function SceneManager(canvas, loadmn) {
console.log("hey hey SceneManager")
const entityManager = new YUKA.EntityManager();
const clock = new THREE.Clock();
const enemies = [];
const gameState = ['running', 'paused', 'end'];
let currgameState = null;
const screenDimensions = {
width: canvas.width,
height: canvas.height
}
//Get models
let playerModel = loadmn.getPlayerModel;
console.log(playerModel);
let enemyModel = loadmn.getEnemyModel;
console.log(enemyModel);
我的逻辑很简单,加载负载管理器并加载模型,这样我就可以在我的场景管理器中使用它们。
但是在日志中我可以看到加载管理器首先调用它们而不是加载模型,它打开场景管理器,甚至在其他导入模块之前开始调用模型。
任何想法为什么会发生这种情况,我该如何解决这个问题,以便在调用场景管理器之前加载模型?对不起,我对 javascripts 有点陌生。
解决方案
问题是加载资产是一个异步操作,您不必等到加载完成后再访问玩家和敌人模型。
我建议你重构LoadManager
一下并引入一个init()
方法。此方法返回如下承诺:
init() {
return new Promise( ( resolve ) => {
this.loadingManager.onLoad = () => {
resolve();
};
} );
}
在您的main.js
中,您使用新方法,如下所示:
loadmn.init().then( () => {
const canvas = document.getElementById("canvas");
const sceneManager = new SceneManager(canvas, loadmn);
// more logic
} );
还有其他方法可以实现此功能(例如通过async
/ await
),但对于开始它应该可以解决问题。
推荐阅读
- javascript - 带有暂停/恢复计数器的 setTimout 未在渲染时更新
- ocaml - 删除警告此表达式在 Ocaml 中应具有单元类型
- javascript - Rails 从 5.2.4 更新到 5.2.5 会破坏资产
- javascript - 在 td 中访问和禁用/启用输入类型日期
- mysql - 如何将 PHPMyAdmin SQL 转储文件导入 mySQL DB
- javascript - React:更改子组件后如何正确更新父组件的状态
- javascript - 如何从javascript中的数组中过滤掉json对象
- p5.js - 如何在 p5.js 中等待
- typescript - why my icon don't change when i'm clicking on ? (ionic/vue/ts)
- javascript - 如何在 React Native 中保存 SVG 输入?