[LayaAir 2.0]资源回收的清理不干净的bug

最近这项目老是内存泄漏,很窝火,后来发现总有资源回收不干净,发现了一些问题,写了个小示例,麻烦官方大佬看一下
 
recycle1() {
        var myscene = new Laya.Scene3D;
        Laya.Sprite3D.load("Models/Ball.lh", Laya.Handler.create(this, function(sp){
            for(var i=0; i<3; i++){
                var ball = myscene.addChild(sp.clone());
                ball.name = i.toString();
            }
            console.log("add finished: ", myscene.numChildren);
    
            for(var i=0; i<myscene.numChildren; i++){
                console.log(myscene.getChildAt(i).name)
                myscene.getChildAt(i).destroy();
            }
            console.log("recycle func1 finished: ", myscene.numChildren);
        }))
    } 
    recycle2() {
        var myscene = new Laya.Scene3D;
        Laya.Sprite3D.load("Models/Ball.lh", Laya.Handler.create(this, function(sp){
            for(var i=0; i<3; i++){
                var ball = myscene.addChild(sp.clone());
                ball.name = i.toString();
            }
            console.log("add finished: ", myscene.numChildren);
    
            for(var i=0; i<myscene.numChildren; i++){
                console.log(myscene.getChildAt(0).name)
                myscene.getChildAt(0).destroy();
            }
            console.log("recycle func2 finished: ", myscene.numChildren);
        }))
    } 
    recycle3() {
        var myscene = new Laya.Scene3D;
        Laya.Sprite3D.load("Models/Ball.lh", Laya.Handler.create(this, function(sp){
            for(var i=0; i<3; i++){
                var ball = myscene.addChild(sp.clone());
                ball.name = i.toString();
            }
            console.log("add finished: ", myscene.numChildren);
    
            for(var i=myscene.numChildren-1; i>=0; i--){
                console.log(myscene.getChildAt(i).name)
                myscene.getChildAt(i).destroy();
            }
            console.log("recycle func3 finished: ", myscene.numChildren);
        }))
    }
 
如上,三种资源回收的方式的输出结果如下:
 
add finished:  3
0
2
recycle func1 finished:  1
 
add finished:  3
0
1
recycle func2 finished:  1
 
add finished:  3
2
1
0
recycle func3 finished:  0
 
可以明显看出,只有第三种反序遍历清理的方式能清除干净。
仔细看了引擎的代码,引擎在很多资源回收的地方使用了1和2的方式,还有使用for in遍历的方式回收的,麻烦大佬确认一下是否有问题。
已邀请:

153*****215

赞同来自:

我代码里很多第二种写法,遍历时移除第一个,现在全改成倒序了,但是引擎里这种写法随处可见,会不会踩雷啊-0-

158*****896

赞同来自:

之前遇到过这问题,然后直接把Scene3D的对象=null

熊猫大侠

赞同来自:

你的 第1,2种写法本来就是错的

柒汐夜

赞同来自:

根据源码来看,numChildren返回的是“子控件数组”当前长度,子控件销毁会从从父节点的“子控件数组”移除,所以出现这种问题本质上算是js数组的性质,当你从数组里移除了元素,那么数组本身长度也会变化;
所以第一种第二种本身写法就不对,而不是说不能那么写,正序的写法应该是:
while(myscene.numChildren) {
    myscene.getChildAt(0).destroy();
}
然后附注一句,官方有坑那是一定的,但是做引擎销毁渲染节点是很基础的东西,我不相信它这么坑。。;d3里的destroy的方法是很多,但是大部分不存在“从数组里移除”的问题,那算是正常的代码。

要回复问题请先

商务合作
商务合作