I found memory leak when dispose mesh with skeleton animation, which use gltf loader
when I use scene loaded in GLTF file, I find that dispose function in Mesh class doesn’t dispose skeleton, which cause the bone texture can’t dispose; and I find that mesh attached the bone can’t dispose too.
I add the code in glTFLoader.ts,show like this, which cause skeleton and bone-attached mesh can dispose when dispose the skeleton-mesh. What things I should care anyway? Thank you.
Note: I think the owner of skeleton ins’t the mesh, and I add the code in gltf Loader, not the Mesh class.
// code in loaders/src/glTF/2.0/glTFLoader.ts
const assignSkeleton = (skeleton: Skeleton) => {
this._forEachPrimitive(node, (babylonMesh) => {
babylonMesh.skeleton = skeleton;
// TODO: dispose skeleton and mesh attatched bone when dispose mesh
babylonMesh.onDisposeObservable.addOnce(() => {
for (let bone of skeleton.bones) {
bone.dispose();
}
skeleton.dispose();
});
});
};
Woot! I’m pretty sure I already answered that question
As the skeletons can be shared, it is not the mesh responsibility to dispose it.
Also please note that calling skeleton.dispose() will dispose the bones so your code could be:
const assignSkeleton = (skeleton: Skeleton) => {
this._forEachPrimitive(node, (babylonMesh) => {
babylonMesh.skeleton = skeleton;
// TODO: dispose skeleton and mesh attatched bone when dispose mesh
babylonMesh.onDisposeObservable.addOnce(() => {
babylonMesh.skeleton.dispose();
});
});
};
Or even simpler:
scene.onMeshRemovedObservable.add(mesh => {
if (mesh.skeleton) {
mesh.skeleton.dispose()
}
});
2 Likes
hello,I want to know something about _activeSkeletons in scene.After I dispose the skeleton,the skeleton is still in _activeSkeletons.Is my disposed method wrong?thank you~
the _activeSkeletons will be cleared on the next render. So you are not doing anything wrong
I don’t mean to necro this, but I believe there is more to this problem. (Babylon.js v4.1.0-beta.4 )
In my project (an mmorpg), models (entities) die, poof, come back, etc hundreds of times. After a few hundred of these cycles, my framerate goes from 100+ down to 30 (and worse as I continually cycle in/out entities).
What I’m seeing is that if I spawn 100 entities, then wipe them, my dispose code runs but there are still skeletons left in _activeSkeletons. Hundreds at times despite there being no active “entities” in my game.
My model setup is to:
- Load the .babylon model, and keep it in a modelCache.
- When an entity is spawned, I look up the necessary model I need and clone it, as well as clone the skeleton.
- When the entity is told to poof, I (in this order) stop the animation on the skeleton, dispose mesh.skeleton, then the mesh, then scene.removeMesh(entity.mesh).
That last step might not be needed, but whatever.
I’ll follow up with a video tomorrow.
Here is the video as promised:
1 Like
I’ve been managing this collection with:
if (g.world.scene._activeSkeletons.data.includes(ent.mesh.skeleton)) {
g.world.scene._activeSkeletons.data.findAndRemove(ent.mesh.skeleton);
}
findAndRemove is just a prototype function for indexOf/splice.
… with no apparent negative effects so far.
1 Like