Animation Event performance degrades severely depending on amount of components on animated object

I noticed that the performance of Animation Events is… really bad.

Here’s a look at the profiler with 400 animated objects triggering an animation event within the same frame. The triggered method is entirely empty to make sure the lag spikes aren’t caused by my own code:

This screenshot is from a reproduction project, there’s nothing running but the animations. It has been submitted as case #699102.
What’s worse is that animation event performance directly depends on the amount of components that are attached to the animated object, as the reproduction project demonstrates.

And to show that this is not just a constructed worst-case scenario, here’s a profiler screenshot from a real project:


~20ms per frame spent just triggering animation events :eyes:

Are you saying this is a regression from 5.1?

Yes, sorry. At least partially, that is - I originally noticed and reported the problem in 5.0.2 (not sure if it’s a regression from 5.0.1 or an even older problem), but it became significantly worse in 5.2 beta.

Here’s the profiler showing the same scene as in the second screenshot in the original post, but running in 5.1.1p1:


~9ms still seems excessive to me for what’s more or less just a method call (and prohibits us from using animation events just as much in the end), but notice that this time at least doubled with 5.2 beta.

Should I submit a separate bug report from within the editor for 5.2 beta?

1 Like

Yes, please submit a new report - it could help to reference the previous bug number in the report, but it’s generally helpful to have it confirmed that the problem still exists in a bleeding-edge version.

Also, FWIW: the time taken here is almost certainly not going to be in the method call itself, but in locating the component(s) that the method call is implemented on. That’s why it depends on the number of components; the more components you have, the more components it has to scan through, looking for methods.

Alright! Submitted as case #710198 (for the future - should bugs generally be resubmitted for major new releases if they can still be reproduced? Or can old reports be updated somehow to confirm that?).

Yeah…I suspect it’s using reflection on all components to find the method that it needs to call, every single time the animation event is triggered…or something along these lines.
I imagine automatically caching the method location could be tricky, since it needs to react to hierarchy changes/component additions/removals? Optionally caching it from within the Animator initialization/manually using an API call would be good enough for me. I suspect our project is one of the more extreme cases for this problem, but I hope I could show that solving this in some way would be very valuable.

1 Like

Hi Sebioff,

We are already working on a solution, like superpig said most of the time is lost for searching for each method in each component, unfortunately the solution won’t be available for 5.2 because is too risky at this time of the release.

Hey!

Super happy to hear that it’s been recognized and is being worked on, so that’s alright! Thanks for the info :slight_smile:

Somewhat big unrelated question: do you think moving Mecanim off the main thread is a possibility in the long term? It’s by far our biggest CPU cost at the moment (not unexpected with hundreds of characters of course).

Most of mecanim is already multithreaded: Animation clip evaluation, Retargeting for human, IK evaluation and even the step to write the animated values into properties is multithreaded.

The only thing left on the main thread is job scheduling and everything related with scripting: fire animation events, fire state machine behaviour, apply on animator move, apply on IK. There is some ongoing work to try to multithread scripting but as long as this is not ready we cannot move all mecanim off the main thread.

Since we are on this topic, why are private methods available for Animation Events? For a production project, there are like 100 of private calls which are exposed, making setting AnimationEvent difficult. Just look at Third Person control sample, already alot of private functions.