Search Unity

2D Animation performance issues

Discussion in 'Animation Previews' started by Rafarel, Oct 15, 2019.

  1. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    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.

    Code (CSharp):
    1.  
    2. private void SetAnimateProps(Transform container, bool animate = true)
    3. {
    4.     int found = 0;
    5.  
    6.     for (int i = 0; i < container.childCount; i++)
    7.     {
    8.         Transform child = container.GetChild(i);
    9.         Animator animator = child.GetComponent<Animator>();
    10.  
    11.         if (animator != null)
    12.         {
    13.             if (animate)
    14.             {
    15.                 animator.playableGraph.GetRootPlayable(0).Play();
    16.                 //animator.StartPlayback();
    17.                 //animator.speed = 1;
    18.             }
    19.             else
    20.             {
    21.                 animator.playableGraph.GetRootPlayable(0).Pause();
    22.                 //animator.StopPlayback();
    23.                 //animator.speed = 0;
    24.             }
    25.  
    26.             found++;
    27.         }
    28.     }
    29.  
    30.     Debug.Log("Found " + found + " animated props in " + container.name);
    31. }
    32.  
    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 :)

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

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    233
    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!
     
  3. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    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.

     
  4. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    Hi did you install the burst package after installing 2D Animation 2.2.1-preview.2?
     
  5. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    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.
     
  6. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    Hi, do you mind send an export from the profiler via IM?
     
    Rafarel likes this.
  7. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    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.
     
  8. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    So one possible way to help with your improvement will be by disabling the SpriteSkin component as well. This will prevent it from updating.
     
  9. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    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!
     
  10. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    Ah right, for now you would need to do something like this

    Code (CSharp):
    1.  
    2.     static class SpriteSkinExtension
    3.     {
    4.         static public MonoBehaviour GetSpriteSkinComponent(this GameObject gameObject)
    5.         {
    6.             var components = gameObject.GetComponents<MonoBehaviour>();
    7.             foreach (var c in components)
    8.             {
    9.                 var type = c.GetType();
    10.                 if (type.FullName == "UnityEngine.Experimental.U2D.Animation.SpriteSkin")
    11.                 {
    12.                     return c;
    13.                 }
    14.             }
    15.             return null;
    16.         }
    17.     }
    18.  
    Note that if you upgrade to the verified version i.e 3.x, we have removed the Experimental namespace.
     
    Last edited: Nov 4, 2019
    URocks likes this.
  11. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    How can you use
    gameObject.GetComponents();
    without specifying the type ? And I just can't have the SpriteSkin type available...
     
  12. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    Sorry was typing the code from memory. Have updated the code snippet on top.
     
  13. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    Ho yes I see, thanks a lot Leo, I'll try this asap.
    I think you can change
    static public
    for
    public static
     
  14. Rafarel

    Rafarel

    Joined:
    Jul 21, 2017
    Posts:
    197
    @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.
     
  15. Leo-Yaik

    Leo-Yaik

    Unity Technologies

    Joined:
    Aug 13, 2014
    Posts:
    344
    No problem. We will definately continue trying to improve the product!
     
    Rafarel likes this.
unityunity