Hi, I have an A-FRAME project where I generate enitities dynamically, but remove them later in the experience (the entities have gltf-attribute attached with textured GLB mesh.
I use this.el.parentNode.removeChild(this.el) for removing the entities - this indeed removes the entity from the DOM and i can isnpect this in the 8th wall stats window.
However when looking at Geometries and Textures rows in the stats window, these numbers keep increasing as if the GLBs are stucked in memory. As expected this has impact on the performance. How to properly dispose of entities with GLB meshes and free them from memory?
Here’s how you can ensure the resources are fully disposed of:
Removing the Entity: You’re already doing this part by using this.el.parentNode.removeChild(this.el). However, A-Frame provides a .remove() method that might handle some additional cleanup automatically. Consider using this.el.remove(); if it’s not what you’re already doing.
Dispose of Geometry, Material, and Texture: You need to manually dispose of these resources. This can be done by accessing the mesh of your GLB model and then disposing of its components. You can use an event listener for the model-loaded event to access the model once it’s loaded, or directly access it if you’re doing the disposal later in the experience.
Here is an example of how you might dispose of a GLB model’s resources:
function disposeEntity(entity) {
if (entity.object3D) {
entity.object3D.traverse(function(node) {
if (node.isMesh) {
if (node.geometry) {
node.geometry.dispose();
}
if (node.material) {
if (Array.isArray(node.material)) {
node.material.forEach(material => material.dispose());
} else {
node.material.dispose();
}
if (node.material.map) node.material.map.dispose();
if (node.material.lightMap) node.material.lightMap.dispose();
if (node.material.bumpMap) node.material.bumpMap.dispose();
if (node.material.normalMap) node.material.normalMap.dispose();
if (node.material.specularMap) node.material.specularMap.dispose();
if (node.material.envMap) node.material.envMap.dispose();
// Dispose any other maps you might have
}
}
});
}
// Finally remove the entity
entity.remove();
}
This function traverses all children of the entity’s object3D, disposing of geometries and materials if they exist. Note that you may need to adjust the function depending on the specific properties of your materials (e.g., if you’re using additional maps beyond those listed).
Consider the Asset Management System: A-Frame’s asset management system caches assets to make them quicker to load. If you’re dynamically loading and unloading many assets, you might also want to manage this cache to ensure it doesn’t grow indefinitely. This can involve manually removing assets from the cache if they’re no longer needed.
Monitoring and Debugging Memory Leaks: Use browser developer tools to monitor memory usage and identify leaks. Tools like the Chrome DevTools Memory tab can help you take heap snapshots and track down memory leaks.
Following these steps should help you manage memory more effectively in your A-Frame project, improving performance and avoiding issues with increasing geometry and texture counts.
I have a big project multiple scenes (13 different scenes) and I notice that once I visit about 5 or 6 scenes I start seeing objects disappear when returning to previously visited scenes. I then added THREE.Cache.clear() before leaving a scene and it allowed me to visit about 8 scenes but then objects started to disappear again. In the code you outlined above do I need to have add a script that goes through the current scene and then calls your function for each entity?
I believe what you have will work, just wondering how to implement it.