繁体   English   中英

JavaScript函数只会占用最后一个元素(Three.js)

[英]JavaScript function only shoes the last element (Three.js)

我正在尝试使用Three.js创建围栏生成器函数,但是我的函数仅返回最后一个围栏,我不知道为什么...

function generateFence(nb){
  var i;
  var value = -5;
  var loadingManager;
  for(i = 0; i < nb ; i++) {
    var arrayFence = [];
    loadingManager = new THREE.LoadingManager( function () {
      scene.add( arrayFence[i] );
    });

    var loader = new THREE.ColladaLoader( loadingManager );
    loader.load( 'fence/model.dae', function ( collada ) {
      arrayFence[i] = collada.scene;
      arrayFence[i].position.x = value;
      arrayFence[i].position.z = -5;
    });
    value = value + 3;      
  }
}

generateFence(3);

您的代码有两个问题,但是我认为问题是旧的async问题。 加载程序是异步的,这意味着代码实际上在以后执行,但是您的代码假定它是同步的。 因此,完成所有循环后,所有篱笆都将读取value ,并且通常只有在全部完成之后才触发它们。 这是一种重构函数以使其按预期运行的方法:

 function generateFence(nb){ // First we will load the model once, as we want to reuse it. // Lets wrap it in a promise so its easier to use later. const value = -5; const fences = new THREE.Group; const model = new Promise(function( resolve ){ THREE.ColladaLoader( loadingManager ).load( 'fence/model.dae', resolve ); }); // Use a `let` declaration to ensure that each loop remembers // what the value for i was wen it ran, even if you perform an async operation. for( let i = 0; i < nb; i++ ){ // The bit after `then` happens asynchronously, waiting until the model is loaded // Because of this, we need to ensure we don't rely too much on values defined in the synchronous loop. model.then(model => { // Let's clone it so we create copies of the one model const fence = model.scene.clone(); // Calculate the x position based on value and the current state of i. fence.position.set( value + i * 3, 0, -5 ); fences.add( fence ); }); } return fences; } // Returns a THREE.Group. When the fences are loaded, they will // be added to the group, which is already an invisible part of the scene. scene.add( generateFence(3) ); 

问题可能是所有围墙都完全相同,并且由于异步操作,所有计算出的围墙都位于同一位置,就像只有一个围墙一样。

有几个问题。

  • 该代码正在为每个围栏创建一个加载管理器。 您最多只需要一个
  • 该代码将相同的篱笆加载5次。 它可能应该加载一次并克隆它
  • 除了等待场景,代码没有对加载管理器做任何事情,但是它已经从ColladLoader获取场景,因此根本不需要加载管理器。 加载管理器用于帮助等待加载多个事物,但这仅加载一件事
  • y代码在回调中使用value ,但是只有value的一个实例。 所有回调都将是相同的,因此所有围栅都将位于完全相同的位置。

这应该工作。

 function generateFence(nb){ const loader = new THREE.ColladaLoader(); loader.load( 'fence/model.dae', function ( collada ) { const copy = collada.scene.clone(); scene.add(copy); let value = -5; for(var i = 0; i < nb ; i++) { copy.position.x = value; copy.position.z = -5; value = value + 3; } }); } generateFence(3); 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM