Tips for optimizing skinned/boned characters?

The only thing that seems to affect my frame rate is the number of characters on screen. (Well, that and portals). Everything else I throw at it - massively complex scenes, physics, shadows and so on it just shrugs off.

The characters are all GLTF, low-poly (couple thousand per character) and about 20 bones. I see significant frame rate drop after about a dozen characters on screen. I’ve run all the animations through the GLTF resampler.

Any general tips / suggestions on improving performance for character models?

Set visible to false for all bones.

mesh.traverse(function(child){


if(child.isBone){ child.visible=false; }


var children=child.children;


if(children.length>0){
child.updateMatrixWorld=function(){
this.updateMatrix();
this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix);
for(var i=0,l=children.length;i<l;i++){
children[i].updateMatrixWorld();
}
};
}
else{
child.updateMatrixWorld=function(){
this.updateMatrix();
this.matrixWorld.multiplyMatrices(this.parent.matrixWorld,this.matrix);
}
}


});


}

So, I tried setting bones to visible=false. This didn’t appear to have any effect on framerate. Also, it introduced a bug: the way I have characters wielding weapons is to set the weapon as a child of the weapon bone, when the bone is not visible the weapon does not appear. Oh well.

Are the characters all duplicates of the same thing or variants?

Here’s a test scene which might make the answer clearer:

There are 5 unique models in this shot, each model has been cloned using SkinningUtils, and then the materials on the clone replaced to provide for color schemes for each actor.

Is this all accurate?

  • about 10–20 SkinnedMesh instances
  • about 20 bones per SkinnedMesh
  • < 100,000 total vertices

If that’s all true and the performance is cratering, do you think you could create a demo for debugging? I don’t know why this would be slow, but it seems reasonable to consider it a performance bug we should fix.

Some users have set up GPU instancing to support different colors per-character, which can definitely get you a lot more characters on screen, but that much effort shouldn’t be necessary to render 10-20 characters…

I’ll put it on my todo list, but it may be a while. I can give you a private link to the game deployed on vercel, but if you need to look at the uncompiled source, or a minimal-code repro example, that will take somewhat longer. (I’m in the middle of a massive migration, 70k LoC :confused: )

So it turns out that the primary slowdown was due to physics - doing shapecasts to determine whether the character was standing on a solid surface. There are some minor slowdowns due to rendering skinned characters, but not nearly to the extent that I first believed. I started to create a free-standing demo of animated skinned characters, but with no physics it runs at 120fps with 25 characters.

1 Like