How I dispose the skeleton and animations cleanly

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 :slight_smile:

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 :wink:

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