Animations cpu bottleneck, would mecanim improve?

I am attempting to make an rts aimed at desktop pc’s only, and large numbers of units on-screen are a must. But so far, from what I have tested, it seems like the number of animations on-screen is severely bottlenecking my game right now. When I have 300 units on-screen, during a big battle, (and NOT animated), I get 50 fps. During the same test conditions, WITH animations enabled, I get 29 fps.

In the stats window it seems like it’s the cpu that’s hurting, as the main thread is usually what increases by about 10 ms. I am using 1 bone per vertex in my skinned mesh renderer quality. I also am using 29 bones per character (i.e. 29 bones in my rig), which I could reduce, but from the optimizations reference seems fairly reasonable.

So I have two main questions (note: I am using Legacy animations right now):

  1. Why are animations stressing the cpu? Shouldn’t they be stressing the gpu?

  2. I read in the mecanim introduction a very brief sentence that said that the retargeting feature in mecanim would save cpu cycles. But it doesn’t say how much. Would switching to mecanim from legacy save me a lot in performance?

I almost feel like I MUST use multi-threading somehow in order to achieve the performance I’m after. But as we all know, Unity is not thread-safe etc… And even if it was, utilizing multi-threading in regards to animations would be even more difficult. Is there anything I can do to reach my units on-screen goal without having to resort to something like 10 bones per character?

  1. The actual animation playback and skinning happens on the CPU, we’ve considered moving this to GPU many times. But some games are limited by CPU and others by GPU, so moving skinning to GPU will only help on some games.

  2. Probably not, Mecanim performs better in complex situations, doing animation blending, layers and IK. But in a simple play one animation scenario I believe the difference to be small.

If you really need 300 characters with 29 bones each I can see how that actually uses a significant part of your cpu.

The normal approach for RTS games to achieve numbers like that is using Mesh Instancing, where they essentially bake all animations into a number of complete meshes. And then each frame you set the correct mesh on each game object. We don’t have an automated framework for that, but you can write your own using the SkinnedMeshRenderer.BakeMesh api and some creativity.

Baking animations to meshes would currently be easier in Legacy as that gives you easier access to forcing an animation state for capturing.

Thanks for the reply UnLogick.

I will look into Mesh Instancing then. Thank you for referring me to this.

Just another thought though, since the animation playback and skinning happens on the CPU, would it theoretically be possible then to make use of cpu’s with multiple-cores to speed this process up? I know that Unity most likely will not have multi-core support, at least for awhile, if ever. But would this be something that is possible in the future?

Meanwhile, I will look into mesh instancing. :slight_smile:

@Velo222: Skinning is already multi-threaded in Unity.

Interesting. Well if this is the case, perhaps I’m thinking of another part of the animation process.

Mesh instancing might be my only hope :face_with_spiral_eyes: I’m currently looking at the Megafiers addon on the asset store, along with point-cache processes. I’m just not sure if this is kind of the same thing as baking an animation into a mesh. It might be exactly what I need, it might also not be what I need lol.

For starters, I’m pretty unfamiliar with the whole animation baking concept. I have a lot to learn, but I’m at a loss as to how to find out the information I’m seeking right now. A quick search on google reveals only one thread involving mesh instancing that’s even somewhat useful.

If you render 300 characters, you could also try an approach using RenderTextures, but it will only work if at least some of your units are of the same type and oriented approximately in the same direction:

Calculate the pose of the first of you similarly oriented units, then render that into a RenderTexture.
For all other similarly oriented units of the same type: render a billboard using the previously generated RenderTexture instead of the mesh.

I’ve never tried it by myself but have read it somewhere.

Regarding bone animation on the GPU side:
I don’t think it possible at all to do it on the GPU, i.e. in a shader. The Mesh object has a boneWeights member (consisting of weights and indices). But the appdata_full struct has no boneWeight nor boneIndices members and as far as I know, it’s not possible to define custom vertex attributes.
I shall be corrected, if I’m wrong.