Removing meshes from scene

For some reason, running this script always removes just half of the meshes:

   scene.meshes.forEach((mesh) => {
         mesh.dispose();
   });

If I have 20 meshes, it will remove 10
Running it again, will remove 5, then 4, 2 and 1…

Am I doing something wrong?

just an idea: try adding a condition. :

scene.meshes.forEach((mesh) => {
         if (mesh)
              mesh.dispose();
   });

Otherwise create a console log to see each mesh in the list before disposing and see what’s wrong.

It seems that running the dispose method with a setTimeout solves this:

    scene.meshes.forEach((mesh) => {
            setTimeout(() => {
                mesh.dispose();
            });
        });

It seems there is an issue with disposing multiple meshes sequentially.

scene.onAfterRenderObservable.addOnce(()=>{
    scene.meshes...?
})

Maybe do it after one render pass has happened?

Removing elements from an array within the callback of forEach causes elements to be skipped. Disposing a mesh removes it from the scene.meshes array, but you can work around that by looping over a copy of the array like below since the copy will remain unmodified when disposing the mesh.

scene.meshes.slice().forEach((mesh) => {
    mesh.dispose();
});

Also here’s some relevant quotes from the MDN page on forEach:
“If elements that are already visited are removed (e.g. using shift()) during the iteration, later elements will be skipped.”

" Warning: Concurrent modification of the kind described in the previous paragraph frequently leads to hard-to-understand code and is generally to be avoided (except in special cases)."

2 Likes

Something like that:

while(scene.meshes.length {
var mesh = scene.meshes[0]
console.log(mesh.name)
mesh.dispose();
}

@Blake I see,
Yes, it indeed seems to be a javascript concern rather than a babylonJs issue. Your suggested solution works great.

Btw, a simple loop has the same concurrent modification issue:

for (let i = 0; i < scene.meshes.length; i++) {
      scene.meshes[i].dispose();
}

I guess this means that the stopping condition in a JS loop is re-calculated for each iteration.

Yes @labris,
Initially I’ve tried your suggested approach and it works as well.
And yet, “while loops” can be intimidating (for me) as perhaps on unforeseen circumstances they can be endless.
For instance, if one of the meshes “refuses” to dispose itself…

Nice to know this lifecycle observable, I didn’t know of it.

Every time you dispose of a mesh scene.meshes.length gets shorter so gets to 0 before all meshes are disposed of. Use while loop. If mesh will refuse to dispose it will tell you :slight_smile:

1 Like

Your debugging suggestion would’ve worked, as I would’ve seen that I’m only iterating on the first half of the meshes as the JS loop end condition kept changing.
Tnx!

Yes, you’re right, that seemed to be the case.
Tnx!