三个 js 从场景中正确移除对象(仍然保留在 HEAP 中) [英] THREE js proper removing object from scene (still reserved in HEAP)

查看:12
本文介绍了三个 js 从场景中正确移除对象(仍然保留在 HEAP 中)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

删除网格形式场景的正确方法是什么?在这个例子中:

 removed_items = [];box = new THREE.Object3D();场景.添加(框);函数添加(){var mesh = new THREE.Mesh( new THREE.IcosahedronGeometry( 10, 5 ), new THREE.MeshPhongMaterial( {color: 0xFFFFFF}) );box.add( 网格 );可移动的物品.推(网格);//干净的();/////当被集成到函数内存中时被正确清理}功能清洁(){如果(可移动项目.长度> 0){可移动的项目. forEach(功能(v,i){v.parent.remove(v);});可移动项目 = 空;可移动物品 = [];}}函数 makeExperiment(r) {变量 i = 0;而 (i < r) {添加();我++;if( r === i ) console.log(r+' finnished ');}}makeExperiment(50);

///之后我手动设置 clean();

正如预期的那样,网格在场景中不再可见,但仍然使用内存,一段时间后会导致内存泄漏和浏览器崩溃.

问题出在哪里,THREE.js 是否做了一些其他的引用?

三.js R73

何时 clean(); 集成在函数中(现在在代码中注释)内存被正确清理.但是当我在 makeExperiment(); 完成后手动设置 clean(); 时,内存没有设置为空闲.

解决方案

我做了一些实验,我认为你的代码没有什么问题.不过,我了解到的一件事是,垃圾收集器可能不会像您认为的那样完全运行.以防万一,我将您的代码包装在 IIFE 中(在这种情况下是好的做法,但不是必需的),并希望在函数完成运行并超出范围后立即清除堆.但它实际上需要一些时间才能清除:

所以我想,好吧,那不是很好,如果我在垃圾收集器只是挥之不去的那个时间跨度内创建更多对象,我就这样做了:

<预><代码>..makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();makeExperiment(50);干净的();

这就是发生的事情:

垃圾收集器似乎在完成它的工作,您为此目的正确地删除了它们.但是,您可能也在使用 THREE.js 渲染器,如果我理解正确的话,渲染器会保留对材质、几何图形和纹理的引用.因此,如果这些未正确处理,它们将不会被垃圾收集.THREE.js 有一个用于 Geometrys、Materials 和 Textures 的方法,称为 .dispose()通知渲染器也将其删除.所以这就是我将如何更改您的 clean() 函数:

removable_items.forEach(function(v,i) {v.material.dispose();v.geometry.dispose();box.remove(v);});

What is the proper way to remove mesh form scene? In this example:

    removable_items = [];
    box = new THREE.Object3D();
    scene.add(box);

    function add() {
        var mesh = new THREE.Mesh( new THREE.IcosahedronGeometry( 10, 5 ), new THREE.MeshPhongMaterial( {color: 0xFFFFFF}) );   
        box.add( mesh );
        removable_items.push(mesh);
        //clean(); ///// when is integrated in function memory is cleaned properly
    }   

    function clean() {
          if( removable_items.length > 0 ) {
            removable_items.forEach(function(v,i) {
               v.parent.remove(v);
            });
            removable_items = null;
            removable_items = [];
          }
    }

    function makeExperiment(r) {
      var i = 0;
      while (i < r) {
        add();
        i++;
        if( r === i ) console.log(r+' finnished ');
      }
    }

makeExperiment(50);

/// after that i mannualy set clean();

meshes are not visible at scene anymore, as expected, but sill using memory, which after some time finish with memory leak and browser crash.

Where is the problem, did THREE.js making some other references?

THREE.js R73

EDIT: when is clean(); integrated in function (commented now in code) memory is cleaned properly. But when I set clean(); manually after makeExperiment(); is done, memory is not set as free.

解决方案

I've done a few experiments and i think there is nothing really wrong with your code. One thing that i've learned though, is that that garbage collector might not run exactly when you think it does. Just in case, I wrapped your code in a IIFE (good practice but not necessary in this case) and expected the heap to be cleared as soon as the function finished running and went out of scope. But it actually took some time for it to clear:

So i thought, okey, thats not to good, what if i was creating more objects in that timespan where the garbage collector is just lingering, so i did:

.
.
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();
makeExperiment(50);
clean();

and this is what happened:

The garbage collector seems to be doing its job, and you are deleting them correctly for this purpose. However, You are probably using THREE.js Renderer aswell, and if I understand it correctly, the Renderer keeps references to materials, geometries and textures. So if these are not disposed of correctly, they will not be garbage collected. THREE.js has a method for Geometrys, Materials and Textures called .dispose() which will notify the Renderer to remove it aswell. So this is how I would change your clean() function:

removable_items.forEach(function(v,i) {
  v.material.dispose();
  v.geometry.dispose();
  box.remove(v);
});

这篇关于三个 js 从场景中正确移除对象(仍然保留在 HEAP 中)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆