jayn

Hi.

In my game, I have a farm screen with 60 plots and each plot has its own skeleton. When test on an Android device the fps drops significantly from 40-60 fps on normal screens to 20-ish fps on this screen, which is a lot of freezes/stuttering.

I've attached my spine project sent via email.

What can I do to reduce this fps drop/poor performance?
jayn
  • Posts: 62

Nate

User avatar
Nate

Nate
  • Posts: 12219

jayn

Thanks, will check it out.
jayn
  • Posts: 62

Nate

Cool, please let us know if you are still having trouble with performance after that!
User avatar
Nate

Nate
  • Posts: 12219

jayn

So I've tried Prune and Clean Up in the editor but it didn't help much.

"If you have many skeletons, it may be acceptable to only update a subset of them each frame, in a round-robin fashion"
If I understand correctly, let's say I have 2 subsets and each update every 2 frames. How can I do this in Libgdx?
jayn
  • Posts: 62

Nate

Often each change makes little difference and many small changes are needed.

You could use a single Skeleton and AnimationState for multiple on screen elements. Apply the AnimationState to pose the skeleton, then position the skeleton and render it for each element. All of the elements will have the same pose, of course. To cut the work needed to pose the skeleton in half, pose the skeleton only every other frame. That is what the text you quoted is talking about.

Check how many draw calls you are using per frame. If that is your bottleneck, using less CPU by posing less often or having fewer bones, mesh vertices, keys, etc won't help much. Set totalRenderCalls to zero at the start of a frame and print it after rendering (and after ending the batch). If you can fit all your texture regions on a single texture atlas page, you can render the whole screen in a single draw call. If you can't, try to organize them to minimize draw calls. If you can't do that either, there are ways to improve it, if they meet your requirements (GLES3.0, etc).
User avatar
Nate

Nate
  • Posts: 12219

jayn

I'm not sure how to re-use the same skeleton on multiple elements. Doesn't it only have 1 skin and 1 position?
jayn
  • Posts: 62

Nate

Maybe this pseudo code helps:
animState.update()
animState.apply(skeleton)
skeleton.setPosition(10, 20)
draw(skeleton)
skeleton.setPosition(30,40)
draw(skeleton)
User avatar
Nate

Nate
  • Posts: 12219

jayn

Thanks for the help.
The result is not exactly what I wanted but I've decided to just reduce the number of skeletons for now.
jayn
  • Posts: 62

Nate

Aye, there are only certain scenarios where it makes sense. For example, if there's an army of 100 units, the player probably won't notice that there are only 10 unique poses.

It's important to first identify your bottleneck, so you know where to focus your efforts. Did you check how many draw calls you are using?

Did you try halving your animation frame rate? For example:
// Half the skeletons are posed on even frames:
if (Gdx.graphics.getFrameId() % 2 == 0) animState1.apply(skeleton1);
// The other half on odd frames:
if (Gdx.graphics.getFrameId() % 2 == 1) animState2.apply(skeleton2);
User avatar
Nate

Nate
  • Posts: 12219

jayn

Cool, that was the code that I was looking for. It seems like the frames drop is due to the combination of draw calls/flushes, the amount of skeletons and older device. I've asked other users with newer devices and they don't have any issue on this screen.

Appreciate it.
jayn
  • Posts: 62

Nate

Glad that helped!

Another thought, you could check Gdx.graphics.getFramesPerSecond() and only when it drops below some amount (30?) would you halve the animation frame rate.
User avatar
Nate

Nate
  • Posts: 12219


Return to Runtimes