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
Thanks for reading me, do not hesitate to ask questions !
Have a nice day !
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.
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.
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.
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.
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.
@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.