I'm trying to create a fence generator function with Three.js , but my function only return the last fence, I don't know why...
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);
There are a couple of problems with your code, but I think the issue is the old async
problem. Loaders are asynchronous, which means that the code is actually executed later, but your code assumes it is synchronous. Because of this, all your fences are reading the value
when all the looping has been done, and they will usually only trigger after they are all done. Here a way to refactor your function so it behaves as expected:
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) );
The issue is probably that all fences are exactly the same and, because of the async operation, all calculated to be in the same place, looking like there is only one fence.
There's several issues.
value
in a callback but there is only one instance of value. It will be the same in all the callbacks so all the fences will be at the exact same place. This should work.
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);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.