Elegant GPU Animation in Unity
TL;DR: On Github, I posted a GPU Animation package that you can get HERE.
GPU Animation For Many Characters
When you want to draw a LOT of characters at once, using Skinned Meshes in Unity quickly hits a performance wall. You could probably get away with 100, but 1000 will be death. There is a solution though. Instead of using bones, you can use a shader to animate the vertices. Each vertex gets associated with a pixel on a texture which was sampled from the original animations.
So each row represents all the vertices on the model. And then along the Y axis we've got time, broken up in to a section for each animation. Just sample the correct pixel's RGB, treat that as XYZ and you can put the vertex in the right place in a vertex shader.
The problem is that there is no built in way to do this in Unity.
For a while, I've been trying to get by with an Asset Store package called Mesh Animator. This tool was first released in 2014 as a CPU based mesh animation tool. It worked in a much simpler way, basically flipping through blend shapes. Somewhere along the way the author added in a GPU solution and it's quite well done, but the fact that's added onto the old method means there is a lot of extra stuff that I don't want. On top of that, the project has accumulated a few tough bugs. The author is kind and responds via email, but is not actively developing the package any more. Ultimately it's just too risky for me to keep in my project when it's such a fundamental function.
Saved by Open Source
Then the other day I found an open source (MIT) package on Github called Mesh Animation. It is a complete package but still minimal and elegantly written by VladV. I love the pipeline. You make a single asset which holds everything - references to animations, materials, and textures. This asset provides the baking interface and even has cool validation functionality courtesy of (the required) Tri Inspector, also by VladV.
While it was a great foundation, I found that when I went to use it, it wasn't set up the way I'd like. Luckily it is minimal so making changes wasn't that intimidating. I ended up forking the project and pushing my changes up to Github. My version is called GPUAnimator. More details are on the Github page.
Below you can see the improvement between GPU and regular skinned meshes.
Method | Batches | FPS | ms |
Skinned | 847 | 90 | 11.0 |
GPU | 18 | 260 | 4.0 |
Let me know if you use it and how it goes.
Link to GPUAnimator Github project.