最近在改Away3D源码的时候遇到个很郁闷的问题,发现创建的Mesh 释放不掉。
分析源码发现 EntityListItemPool 类中逻辑Bug在getItem()函数中发现_poolSize 对象池大小如果够用的情况下 它采用的方式是复用EntityListItem
那么假设我删除了场景上有10个对象我全部删除了然后我再创建9个 这时候总有1个对象是被缓存着的。一直要等到我创建第10个对象他才会被释放掉。
没辙了跑到 看看对象销毁流程吧。
对象被销毁时会调用 Scene3D 的 unregisterEntity函数,这个函数只是删除了Scene3D 和 显示对象的引用。但是EntityListItemPool中还是存在实例引用
看了看收集器 每次都要经过 Scene3D 的 traversePartitions函数。
那我先在unregisterEntity函数调用的时候做一次记录把要删除的显示对象添加到一个列表中。
private var _unregisterEntityList:Vector.<Entity> = new Vector.<Entity>;
/** * When an entity is removed from the scene, or from one of its children, remove it from its former partition tree. * @private */ arcane function unregisterEntity(entity : Entity) : void { _unregisterEntityList.push(entity); entity.implicitPartition.removeEntity(entity); }这样在下一帧执行渲染的时候我就知道要释放掉哪些对象了。然后修改traversePartitions函数.
public function traversePartitions(traverser : PartitionTraverser) : void
{ var i : uint; var len : uint = _partitions.length; if(traverser is EntityCollector) { while(_unregisterEntityList.length) { var _entity:Entity = _unregisterEntityList.shift(); (traverser as EntityCollector).entityListItemPool.unmap(_entity); (traverser as EntityCollector).renderableListItemPool.unmap(_entity); } } traverser.scene = this;while (i < len)
_partitions[i++].traverse(traverser); }每次在新的一轮收集前把上一帧要清楚掉的对象全部干掉。
然后跑到entityListItemPool 类里添加一段代码:
public function unmap(mesh:Entity) : void
{ var _mesh:Mesh = mesh as Mesh; for(var j:int =0;j<_mesh.numSubMesh;j++) { for(var i:int = 0; i < _pool.length; i++) { if((_pool[i].renderable is SubMesh) && (_pool[i].renderable as SubMesh).parentMesh && (_pool[i].renderable as SubMesh).parentMesh == _mesh) { (_pool[i].renderable as SubMesh).parentMesh = null; _pool.splice(i,1); _poolSize --; continue; } } } }
这样保证了对象的释放。OK 这下好了
测试下了一下没有问题全部乖乖的垃圾回收了。