2D Animation performance issues

Hello there, I’m here to share my experience and some of my experiments.
And I will ask some question at the end of my forum post.

I was very happy with the performance of 2D animation package and used to have a nice and steady 60fps in the stats windows until I upgrade :

  • Unity from 2019.1.8 to 2019.2.6
  • 2D Animation from 2.1.0-preview.5 to 2.2.0.preview.5
    (I do not think that Unity itself is causing troubles but I upgraded both at the same time)

I have a simple 2D Level for a Tower Defense game with some animated props that are in a game object container for animated props.

I red in this forum that there are some performance issues with this 2D animation package and that the Unity team is aware and are working on it (right @Leo-Yaik ?). So I decided to write a simple script to pause all the animations that are on my scene to be able to work on balancing the game in the editor with a comfortable frame rate. The script is just searching for game objects that has an animator then pause the animation. It worked great for a short period, but not in all cases. Then I decided to update 2D animation package again due to a new release, and I’m now in 2.2.1-preview.2. Now my temporary patch does not work at all, the performances are very low even if all animated props are in pause.

I’ll show you my little function I use to pause all animated props in a container, the function runs only once at start of my scene.

private void SetAnimateProps(Transform container, bool animate = true)
{
    int found = 0;
  
    for (int i = 0; i < container.childCount; i++)
    {
        Transform child = container.GetChild(i);
        Animator animator = child.GetComponent<Animator>();

        if (animator != null)
        {
            if (animate)
            {
                animator.playableGraph.GetRootPlayable(0).Play();
                //animator.StartPlayback();
                //animator.speed = 1;
            }
            else
            {
                animator.playableGraph.GetRootPlayable(0).Pause();
                //animator.StopPlayback();
                //animator.speed = 0;
            }

            found++;
        }
    }
  
    Debug.Log("Found " + found + " animated props in " + container.name);
}

Questions

  • Why pausing the animation is not profitable anymore in term of performances ? I would like to have an option in the game to have better performances on low end configurations to stop the animations.

  • What is the best way to pause and resume an animation ?
    You can see in my code that I tried different things :
    playing/resuming animation :
    animator.playableGraph.GetRootPlayable(0).Play();
    animator.StartPlayback();
    animator.speed = 1;

pausing the animation :
animator.playableGraph.GetRootPlayable(0).Pause();
animator.StopPlayback();
animator.speed = 0;

Note that the GetRootPlayable way sometimes throw a null reference exception.

Also that the performances are good in the built version of the game if I have the burst compiler installed, but I need to have good performance in the editor to balance the game :slight_smile:

Thanks for reading me, do not hesitate to ask questions !
Have a nice day !

Hi,

Using animator.playableGraph will retrieve the State Machine Playable Graph, which is generated by the animator and shouldn’t be modified.

There are two ways you could improve performances in this case.

1- Enable/Disable the Animator component and make sure the option Animator.keepAnimatorControllerStateOnDisable is enabled to avoid freeing the State Machine PlayableGraph when you disable the Animator.

2- Create your own PlayableGraph with a AnimatorControllerPlayable node that will drive your state machine. Then, you can call PlayableGraph.Play and PlayableGraph.Stop on it manually to control when the animation needs to evaluate.

Hope this helps!

Thanks for your answer @simonbz

I implemented your first idea, and it worked for pausing and resuming the animations but it didn’t work in term of performance gain. I made a little screen cast of what happened :

  • The game run at 30fps with the animation playing or not.
  • If I delete my game object that contains all the animations, the fps goes up to 90fps.

With previous versions of the 2D animation package I had the same gain of performances when I stopped the animations but not anymore …

Here is a video, sorry for the mouse cursor position, it captured it weirdly, but you should see what I’m talking about.

w0n2n

Hi did you install the burst package after installing 2D Animation 2.2.1-preview.2?

Yes I did ! It clearly improve performances on the built game, but not in the editor in play mode, am I right ?
Right now, I have game designers that just can’t balance the game working in the editor because they have bad conditions for playing and tweaking the game.

Hi, do you mind send an export from the profiler via IM?

1 Like

Hi @Leo-Yaik
I do not know what IM is but I sent you a message with some data, I hope that is what you were expecting.
Thanks for helping me.

So one possible way to help with your improvement will be by disabling the SpriteSkin component as well. This will prevent it from updating.

Thanks Leo but how can I access the SpriteSkin component by code ?
This code don’t work for me : SpriteSkin skin = child.GetComponent<SpriteSkin>();
I can’t resolve the SpriteSkin symbol because its an internal class of UnityEngine.Experimental.U2D.Animation.

Thanks for your amazing support!

Ah right, for now you would need to do something like this

    static class SpriteSkinExtension
    {
        static public MonoBehaviour GetSpriteSkinComponent(this GameObject gameObject)
        {
            var components = gameObject.GetComponents<MonoBehaviour>();
            foreach (var c in components)
            {
                var type = c.GetType();
                if (type.FullName == "UnityEngine.Experimental.U2D.Animation.SpriteSkin")
                {
                    return c;
                }
            }
            return null;
        }
    }

Note that if you upgrade to the verified version i.e 3.x, we have removed the Experimental namespace.

1 Like

How can you use gameObject.GetComponents(); without specifying the type ? And I just can’t have the SpriteSkin type available…

Sorry was typing the code from memory. Have updated the code snippet on top.

Ho yes I see, thanks a lot Leo, I’ll try this asap.
I think you can change static public for public static

@Leo-Yaik disabling the SpriteSkin component is very effective to gain performance in editor. Please tell me when the performance will be better in editor so that my artists do not have to compile the game to test their animations in situation. I’ll update Unity to 20.19.3 really soon to see if there is a difference. Thanks a lot for your premium support.

No problem. We will definately continue trying to improve the product!

1 Like