Alexees

In our game, the 12 spine animations use up most of our performance in our home screen, very noticeable on Android. What our artist did was using one spine along with one atlas, differentiating by animation.

Does this approach make sense or does it increase the amount of work because every instance calculates all bones, being part of a currently running animation or not?

How do we profile what exactly the problem is? Is there a spine profiler? Do we have to use the Unity profile window to see which code path takes the longest?

The deep profiler shows this and it seems like we need to split the animations, using a single atlas still, am I right?

SpinePerformance.png


P.S.: I was searching the esoteric page for something related to performance optimizations and could find nothing but forum threads. A one pager would be nice
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
Alexees
  • Postovi: 12

Mario

We have a one pager here: Metrics view - Spine User Guide: Performance

We'll need more information about your skeletons. And did I understand right, you have one atlas per animation? You don't share an atlas across most of your skeletons? That will incure GPU side stalling, which is very bad for performance.
Avatar
Mario

Mario
  • Postovi: 3027

Harald

Alexees je napisao/la:P.S.: I was searching the esoteric page for something related to performance optimizations and could find nothing but forum threads. A one pager would be nice
The one-pager exists here, we even placed the Performance subsection in the FAQ section so that it's hopefully easier to find. :)
spine-unity Runtime Documentation: Performance
Avatar
Harald

Harri
  • Postovi: 3991

Nick

Hi, Just passing by.

I saw from the screenshot that most of the works done by MathUtils functions and wonder if lookup table is used to speed up things so I just took a inside that class and found that there is indeed code using LUT optimization. However, the flag USE_FAST_SIN_COS_ATAN2_APPROXIMATIONS is actually commented. May be enabling it would help? :think:

I wonder how this spine project with 12 UpdateWorldTranform() yield 5916 Bone.Update() calls.
Must have a lots of bones. :upsidedown:
Nick
  • Postovi: 295

Alexees

It's german, but it should give the idea:

SpineFacts.png


The interesting thing is that in fact, 5916 / 493 = 12
This means each skeleton iterates all bones, being animated or not. I guess this means we need to split up on that level. It seems that it has been a terrible idea to do all animations for different things in one spine. Using multiple with the same atlas should do the trick then.

@Mario we use 1 spine with 1 atlas and mainly 12 different animations that distinguish between the objects
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
Alexees
  • Postovi: 12

Nate

Yes, all bones are updated because the skeleton doesn't know which bones are important to your animations, rendering, or other code that may use a bone for something. You could use skin bones to control which bones are updated -- bones in a skin that is not active are not updated. If you have some other way of knowing which bones don't need to be updated, you could modify the runtime to skip those bones.

Here is the part of the runtime that controls which bones are updated:
https://github.com/EsotericSoftware/spine-runtimes/blob/4.0/spine-libgdx/spine-libgdx/src/com/esotericsoftware/spine/Skeleton.java#L169
The skeleton creates a list called updateCache that is all the bones and constraints that need to be updated, sorted so parent bones are updated first, constraints are applied at the right time, and bones constraints affected are updated afterward.

The logic there for skin bones is a little tricky, but bone.data.skinRequired is true when the bone is in a skin. When sorted is true, the bone will be skipped -- it won't be added to updateCache.

You can modify the bones a skin has to control which bones are updated, just be sure afterward that you call updateCache() on the skeleton to rebuild the list.
Avatar
Nate

Nate
  • Postovi: 11846

Harald

Please also note that you are using a clipping polygon with two triangles, which is expensive computation-wise. When using Unity you might instead want to use one of Unity's mask components (RectMask2D or SpriteMask). Apart from that it is often possible to use a single, very large clipping triangle instead of two to achieve the same effect. The size of the triangle does not matter computation wise, just the number of clipping triangles.
Avatar
Harald

Harri
  • Postovi: 3991

Nate

Oh good point Harald! Clipping is very CPU heavy, try avoiding it completely. If you must use it, use a 3 vertex triangle for the clipping polygon and clip as few vertices as possible.
Avatar
Nate

Nate
  • Postovi: 11846

Alexees

Thanks to you guys,
converting the bones to skin bones let us gain 75% performance
Alexees
  • Postovi: 12

Harald

Glad to hear, thanks for getting back to us! 8)
Avatar
Harald

Harri
  • Postovi: 3991


Natrag na Unity