• RuntimesUnity
  • Optimizing Skeletons

Hey,
We recently discovered a noticeable performance load when we added a ground cracked tile made in spine to our project.
There can be up to 100 of these tiles on screen at the same time.
I started fiddling with the animations and ended up fixing a couple of things that improved performance.

  1. The skeleton uses a cutout mask, so I disabled the mask at the start of the animations in which it is no used.
  2. The skeleton has a couple 1 frame animations that are played in loop. These 2 animations are used for 99% of the time that the tile is on screen. I figured maybe 1 frame animations looping are not so performant because some management must be done when starting/ending a loop, so that would make this steps needed every frame. I just added a dummy key to make these 1 frame animations into 20 frame animations instead.

Number 1 improved performance pretty noticeably. Number 2 was almost not noticeble.

I'd like to know if what I did makes sense and is something I should replicate for the rest of my skeletons and if there is an obvious improvement I'm missing for 1 frame animations. Maybe using FixedTimestepUpdates?

We are already using the UpdateWhenVisible property and it also seems to help.

Thanks for your time.

Related Discussions
...

If by "cutout mask" you mean a clipping attachment, yes, avoid clipping whenever possible:
https://esotericsoftware.com/spine-clipping#Performance

What are you using 1 frame animations for? If it's just to set a pose, you can pose the skeleton by applying the animation once, then just leave it like that. Apply the animation and call skeleton.updateWorldTransform, then each frame just draw the skeleton without doing either of those again.

That may be sufficient to solve your performance issues. If not see here:
https://esotericsoftware.com/spine-metrics#Performance

  • pixelmeat ответили на это сообщение.

    Thanks Nate! I didn't know clipping attachments were so demanding.

    I'm using 1 frame animations to set some objects to static states like the open or closed state of a door when it's not opening or closing.
    What would be the best way to detect a 1 frame animation in code? If I have diferent enemies using the same behaviors I'd like to be able to detect if any of them has a 1 frame "idle" to apply the method you mentioned and loop the rest of the "idles", for example.

    • Изменено

    @pixelmeat I assume that by "1 frame animation" you mean an animation with the key set at the very first frame only. If so, you could either check the current animation's Animation.Duration and check
    if (animation.Duration == 0.0f).

    If you allow a single frame to be anywhere in time, it's a bit more complex: you could iterate over Animation.Timelines and check Timeline.FrameCount and if it only has a single frame, and then also check whether Timeline.Frames[i] is the same time for all Timelines of the animation.

    Edit: I've updated the above posting as I've noticed after the fact that Animation.Duration is 0.0 when the key lies on the first frame.

    • Изменено

    Thanks @Harald. Yes I mean an animation with a single key on the first frame. I'll give a go to the animation.Duration == 0.
    Also, what does @Nate mean when he says:

    Nate Apply the animation

    ?

    • Изменено

    @pixelmeat You can apply an animation to a skeleton without AnimationState, via Animation.Apply(skeleton), which is not something you do often in spine-unity normally. You can see that in the example scene Spine Examples/Other Examples/Spine Gauge, on the Spine GameObject (gauge), component Spine Gauge. See the code here.

    With spine-unity skeleton components, you should consider disabling the component or setting UpdateMode at the component to None to avoid re-generating the skeleton mesh, as LateUpdate would otherwise still perform unnecessary work.

    See:
    https://esotericsoftware.com/spine-applying-animations#Timeline-API

    You can use the Timeline API to apply an animation once. Eg:

    // Once:
    animation.apply(...)
    skeleton.updateWorldTransform();

    That sets the pose then you can render the skeleton many times using minimal resources.

    Perfect! Thanks guys.