簡體   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