KoliJack

Hi all,

We use Spine in our live project and I want to understand how I can reduce spine's memory usage in our project.

Our setup
We run on unity 2019.4.34f.
The game is android and ios.
We have 140 duplicate characters.
We have another 5-35 unique characters. (some of these duplicate depending on player choices).
There are a maximum of 6 skeletons active at the time (they are atlased, but that is accounted for in the character count above).

The problem
In the a level, the player starts with just one character, and then scales up to the 170 mentioned above.
When all 170 characters are active the profiler shows that 75mb of System.Single[] and I have validated that the size of this memory chunk grows as more characters are activated. I have also taken snapshots where I level everything except the number of spine characters, and the memory usage doesn't grow anywhere near as large.

My questions
  • Is it possible to share skel data between multiple entities?
  • What is the most efficient way to use spine with regards to the memory profile?

Attachments
I have attached some snapshots of the memory of the game from unity. Showing 4 characters, roughly 70-80, 170 (max), and a breakdown of the max.
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
KoliJack
  • Postovi: 2

Nate

Your last screenshot shows you have 147 frame values, which is time, x, y for 49 keys. It looks like you are using the 3.8 runtimes, which store 19 values for the Bezier segments for each key. The last key doesn't have a curve, so 48 * 19 = the 912 you see. Note that in 3.8 the 19 values are taken up even for linear and stepped keys.

What version of the Spine Runtimes are you using? You can check memory usage using 4.0, which stores curves more efficiently. It uses 18 values per curve and keys that are linear or stepped don't take up any extra space. I would be interested to see similar screenshots using 4.0.

Some ways to reduce memory is to use fewer keys, use fewer Bezier keys (in 4.0), and, more importantly, to avoid using mesh deform keys. This explains why:
Keys - Spine User Guide: Deform keys

If you want to avoid storing the 18 values per Bezier, you could rewrite parts of the runtime to store 4 values (x,y for two Bezier control handles) and then compute the segments every time they are needed (basically move the code from setBezier into getBezierValue). This is a pretty significant amount of work though, and while you will use less memory, you will use a little more CPU.
Avatar
Nate

Nate
  • Postovi: 11791

KoliJack

Thanks Nate! We're on 3.8 so that seems like a great place to start.

We'll take a stab in an upcoming sprint and let you know how we go.

---

Hey Nate,

Ok, we've upgraded to 4.0 and we do see a significant improvement (almost 50%), so that's great!

Still it would be awesome to see if we can get down from here as spine is still 30-40mb for us.

I'm mostly wondering about the duplicate characters, is there any way optimize them?

It seems like a lot of the data is the skeleton and animation data which is held for each character, is there some way we can hold a single reference to this 'worker' character data and then get all 120 copies to reference that data? It seems like from there they only need to know which frame/animation they are in.
Nemaš dopuštenje za pregledavanje privit(a)ka dodan(og)ih postu.
KoliJack
  • Postovi: 2

Nate

Nice, 50% is great! Thanks for reporting back how it went.

Absolutely, you should not be loading the same skeleton data multiple times. The runtimes are designed to load the data once, then any number of instances all share that data:

Runtime Architecture - Spine Runtimes Guide: Data objects
Avatar
Nate

Nate
  • Postovi: 11791


Natrag na Unity