Some of our target devices for the game we're working on are various Android and Fire TV devices, which have notoriously lousy specs. Our game is currently very simple in terms of things going on and happening, yet on Android TV devices we get abysmal performance, which seems to degrade over time as the Skeletons animate. In the GameScene we are getting just 15 FPS, dropping to near 0 over a few minutes.
I currently have just 3 skeletons in the GameScene, the Player, the Opponent, and the Crowd in the background. The Player and Opponent both have several animations for controlling them in the fight, and the Crowd just has a small number of animations, layered on top of each other, and programatically adjusted for "excitement" through setting the Alpha value of one of the animation tracks per update and adjusting the TimeScale of that track as well. (Excitement wanes over time if "exciting" things aren't happening in the fight.)
The Player, to allow for future player customization, currently sets that Skeleton's Skin, Attachment Colors (using either RegionAttachment.SetColor, or MeshAttachment.SetColor depending on what type of Attachment we are coloring). However we only do this when we call the Player's OnAwake
method, and OnValidate
so it shouldn't be causing any significant issues here, except maybe during loading.
I currently update all three skeletons from a 'GameController' script using SkeletonAnimation.Update
and have set the SkeletonAnimation scripts to "Manual Update" so that we are only updating each skeleton once a frame.
Upon hooking up the Profiler to this Android TV device I've been testing on, I found that most of the slow-down appears to be coming directly from Spine, specifically:
SkeletonAnimation.LateUpdate
SkeletonRenderer.LateUpdate
SkeletonRenderer.LateUpdateMesh
Which takes nearly 55 ms. to complete each frame!
Here is a screenshot of the profiler showing these results:
Any help to solve this issue, and increase our performance on Android TV devices (and most likely old crappy Android phones and tablets as well) would be greatly appreciated!
Edit: A small extra detail is that the Player's SkeletonAnimation is rendered to a RenderTexture so that we can properly handle opacity, and this is essential for getting the look we want for our GameScene. Think Little Mac from Super Punch-Out!! and that is the effect we are making, aside from the fully opaque gloves (though now that I think about, would be very cool). Disabling the Player's SkeletonAnimation entirely, or more specifically: not loading the Player Character's scene Additively, gets us from around 10 FPS to 20 FPS from that single change alone.
Edit 2: Some more experiments, by limiting the scene to a single SkeletonAnimation, and by also setting the Animation Update setting to "In Update" rather than "Manual Update", I was able to get between 40-50 FPS depending on which SkeletonAnimation we are rendering. This is obviously not a solution though, because we need at least these three SkeletonAnimations rendered to the GameScene each frame (the Player, the Opponent, and the Crowd). This is leading me to wonder if the artists are doing something wrong when creating these Skeletons, or inefficiently, or if there are some tricks and tips I'm missing to squeeze the most performance out of these skeletons at run-time. As the Software Engineer of the team, I don't have a great understanding of how the artists have set up these Skeletons under the hood, but can ask them as well as provide Export JSONs to help nail down the cause of these slowdowns.