• Unity
  • Unity Runtime Performance Hacks?

Hi!

I'm working on a game (targeting PC, Mac, Linux) that probably uses a number of Spine characters at once that perhaps would be far higher than expected or supported. Here's my current benchmark, when running 81 animating skeletons of the nature discussed further below:

Изображение удалено из-за отсутствия поддержки HTTPS. | Показать

I would love to bring that 41% down as low as possible. My goal would be to have there be up to 100 zoo visitors at 60fps, but 80 drags it down to 30fps. I understand that SkeletonRenderer.LateUpdate and SkeletonAnimator.Update do a fair bit of work, so what I'm probably looking for are some hacky-approaches that save me some CPU time, but more on that in a bit. First, I've got to do my due-diligence based on what has already been said on these forums on the subject of performance. Sixth months ago Pharan wrote a helpful pointed list to go through to improve performance:

1) Minimize the number of keyed properties in spine. For example: If a bone doesn't need to rotate, don't give it a key to rotate. Anywhere. That item shouldn't have a row in the dopesheet. Each row in the dopesheet is extra overhead. So even if you only have 1 key on it, it'll eat up resources. (Each dopesheet row is one Timeline runtime object that the runtime has to iterate over every Update an animation makes.)

Done! As a result my animations are a bit more mechanical than they used to, but I'm approaching all my timelines with an ascetic approach.

2) Have as few bones and attachments as possible.

Ah, now, I think I'm pretty good on the Bone front. Here's the skeleton in question, the one I had 81 of in the benchmark:

Изображение удалено из-за отсутствия поддержки HTTPS. | Показать

I think the Bones count is inoffensive. I probably could go down to two spinal bones, but would have to go through all my animations to correct for it, so I'm leaving that until I absolutely have to.

The Attachments count, however, are quite high. There are 178 attachments because I have half a dozen skins that share the skeleton. For the skin displayed above, there are just 26 attachments. I imagine the answer is 'of course not' but attachments in skins that aren't displayed in Unity don't drag down the performance, do they?

3) If you can help it, don't use meshes and FFD. And if you really need meshes for these skeletons, minimize their vertex count.

The skin screenshot'd above is entirely made of meshes. But the other 80 skeletons are displaying one of the two Visitor skins, which don't have any meshes.

4) If your skeletons are for looping environment stuff, and you want want it to play one animation over and over, Baking may be a good option, especially if you just want it to do a Weighted/Skinned animation. Baking will take advantage of the GPU to animate the meshes and free up your CPU to do the more controlled things. For maximum compatibility with Unity GPU skinning settings, make sure each VERTEX is bound to a maxmimum of two bones.

I'm really not too keen on baking stuff, because I want to ragdoll these skeletons later on, if I possibly can. I suppose I could swap out a baked version with a non-baked version. The player can't be baked because I'm mixing animations too much, but that's just one skeleton. I've not actually baked anything with Spine/Unity yet, so I don't know how baking to 60fps and displaying that would perform? Can anyone with some experience in this area make any educated guesses as to how that would turn out?

My Ideas

I've had a few thoughts, that essentially come down to what I described earlier as hacky approaches to this problem. For full context, here's a screenshot of the game, showing the one player Skeleton, and some of the eighty Visitor Skeletons:

Изображение удалено из-за отсутствия поддержки HTTPS. | Показать

My first idea is the obvious one, which is just not animate anything that's not on camera. Easy gains there, I'm sure.

The second idea is for skeletons that are far enough away from the camera, to just update their animations at 30fps, even less. The lack of smoothness is very noticeable up close, but I'm guessing less so further away. Slipping a:

if (Time.frameCount % 2 == 0) return;

into the slow LateUpdate and Update methods does really help, but of course I'll have to spread the updates-by-frame across the two frames, otherwise, spikes!

These are the ideas I've got, hopefully I've given enough context in this post to help you with your own suggestions, which are very appreciated. Feel free to ask questions, if I've missed anything.

Related Discussions
...
  • Изменено

I was able to get 200x animated characters walking around on my Nexus4 at a solid 60fps with a few optimizations.

1) Don't use meshes 😛
2) Optimize a bit of the math for scaling since I wasn't using scale keys
3) Most importantly updating frames based on distance from camera.

Mitch написал

1) Don't use meshes 😛

I don't even know what a mesh is, that's how little I'm going to use them.

Mitch написал

2) Optimize a bit of the math for scaling since I wasn't using scale keys

Would love to hear more about this, I'm not using scale keys either.

Mitch написал

3) Most importantly updating frames based on distance from camera.

Glad to hear this worked for you. How did you decide to spread frame updates depending on distance?

There are a few under Advanced in the inspector that should work depending on your setup.
Disable Render Meshes if you're not using meshes.
Enable Immutable Triangles if you never change draw order or enable/disable attachments.

I also see you're using IK.
I think you should be pretty aggressive in getting rid of as many (IK) constraints as you can if you're expecting to spawn that skeleton by the hundreds.

I kinda think your skeleton may still have a few too many bones.
I mean I don't know why your torso has 3 bones.
And I'm guessing you could also sacrifice the foot flexibility by just letting it have 1 joint at the ankle instead of 2 bones per foot. Maybe he could even live without a neck bone, since the neck is barely visible anyway.
But you have better knowledge of what your skeleton needs to do, so that'll be up to your judgement, I'm sure.

Did you do a deep profile and see which smaller/more specific methods are taking a lot of time under the SkeletonAnimation Update and LateUpdate stacks? That can vary a lot depending on your rig.

Thanks Pharan, helpful stuff.

I've started off with not animating anything that's on camera, and created three 'animation settings' levels that dictate when the characters update:

  • High - 60fps, all the time!
  • Medium - 60fps for characters close to the camera, 30fps for characters further away.
  • Low - 30fps for all characters, all the time.
    This seems to give me the greatest gains, and doesn't require me to reanimate or delete bones from my rig. This is the last resort for me!

Here's another observation, the game runs so much quicker when actually exported from Unity. It's only in the engine that I have significant trouble. I haven't really encountered much overhead from the Editor until now, but the High setting I described above works fine for me when exported, but in the Editor Medium or Low will have to do. I'm glad these are good ways to decrease CPU speed, I'm hoping to have the game playable on less powerful computers and laptops. In any case, I'm back to having a couple of hundred animating characters with a game frame rate of 60. Hooray!

Yeah, the editor has considerable overhead the more stuff you have running.

2 года спустя
Mitch написал

2) Optimize a bit of the math for scaling since I wasn't using scale keys

Can you explained more about scale optimization 🙂

Mitch написал

3) Most importantly updating frames based on distance from camera.

Is this means completely disable animation when far from the camera?

You can cull the SkeletonAnimation.enable with OnBecameVisible(), OnBecameInvisible()

3 года спустя

Hello, Im also struggling with spine performance on unity. I would like to:

Pharan написал

Disable Render Meshes if you're not using meshes.

But where I can find option disable this?

You are posting to a 2.5 years old thread, the info above is obsolete already.

The above functionality is provided as part of the spine-unity skeleton components already. Please see the Advanced Parameters documentation section, under Update When Invisible..