Add Bone.ShouldUpdate(let us stop bones not doing anything from hurting performance!)

Ever since roblox released skinned meshes, I’ve been having a lot of fun with them. Some of you may have seen my water demo showcased here and on the blog.

I absolutely love that roblox gave us this power, but it is currently far too limiting for one simple reason.

Bones that aren’t doing anything still incur a large performance penalty

Why

Why is this an issue you may ask? Well, for things like characters which most people are using skinned meshes for, it’s hardly one because you won’t have that many bones in your game.

However, a lot of devs I know, myself included, want to use skinned meshes for things that aren’t character related.

  • Interactive water
  • grass that bends/deforms with your character
  • trees which wave in the wind when your camera is nearby.

All of these things are currently very hard if not impossible to optimize properly, or flat out impossible due the fact that bones/skinned meshes existing in the workplace alone incurs a hefty performance cost.

Proof/Details

I was working on a grass project when I noticed this, and realized something.
I was updating grass in chunks near your camera + viewing frustum, but having the meshes in the workspace even when they were thousands of studs away or not doing anything, still hurt performance.

  • having 50 of my many quad skinned meshes in workspace makes performUpdateCoordinateFrame take 1ms per frame

  • having 50 of the non-skinned version, uploaded using the exact same fbx, doesn’t cost anything

For a quick test, In studio, I just ran a script that duplicates a skinned mesh with 201 bones inside

performUpdateCoordinateFrame takes about 13ms, updateSkinningIslands about 2ms and updateDynamicParts about 12ms

updateDynamicParts can be lowered by cframing the skinned meshes further apart from each other, but it’s not great

basically, updateSkinningIslands seems to scale with number of bones and performUpdateCoordinateFrame seems to scale with bones and triangles/vertices

Whether or not they’re actually updating seems to change absolutely nothing :confused:

Solution

My proposed solution is a simple one, although I’m not sure how simple it is for roblox to implement.
I propose that we simply have a bool value property under a bone or skinned mesh, that acts as a flag for roblox’s skinned mesh update/render code, to skip any of the updates that are hurting performance.

It’s not the cleanest solution but it’s the only way I can think of to allow developers to further utilize this feature and power our imaginations, because currently we are far too limited in what we could use this otherwise incredibly powerful tool for.

Thanks!

48 Likes

For cases like grass and trees you could insert the bones locally only on objects that are near the camera. I could see this being useful for meshes that are deformed but remain static, but I can’t think of any use cases. For water you could create the parts locally and only insert the deforming models around the camera, with more distant ones being static flat meshes. When the part become far away it can snap to the flat model or ease to the flat model depending on if it’s on screen.

I always run an export script on my armatures that renames all of the bones to be 1-character long according to a bone name list (starting at “\1”.) I don’t know if this affects performance, but it certainly reduces the length of custom animation data strings and improves memory usage.

1 Like

For cases like grass and trees you could insert the bones locally only on objects that are near the camera. I could see this being useful for meshes that are deformed but remain static, but I can’t think of any use cases. For water you could create the parts locally and only insert the deforming models around the camera, with more distant ones being static flat meshes.

Well you’ve described what I was already doing for the water(you’ve seen the demo)
Issue with that is that water is one of the only things you can get away with doing this for.

For instance you can just CFrame the same group of trees or grass around your camera, sure, but

  • That’s a Band-Aid solution
  • That will look pretty terrible

The issue is that in order to have animated environments for trees, grass, fast 3D particles, whatever, we need to be able to control what isn’t and what is updating. Because we can’t swap things out for static meshes due to the cost of parenting in and out of the workspace
(and swapping models via transparency doesn’t really work either)

This doesn’t only apply to environment stuff, but we’ve also had a lot of ideas for how to speed up various aspects of our games using skinned meshes to move objects, or even unlock new doors to different kinds of games that were currently impossible(say, RTS games with thousands of more detailed units moving at once). But due to the limitation of not being able to efficiently dictate what roblox should be updating and the fact that there is no feasible way to swap between updating or static meshes to try to hack it in, these things are currently not possible

6 Likes