NeatWolf

Hi,

I'm creating a per-view path-based crowd system of walking 2D characters with some randomization on walking speed, in a 2D side view, orthographic scenario.

I already took into consideration culling and other parameters, they should be all set to achieve maximum performance. Also, I'll be recycling every character getting out of view by wrapping its position on the other side of the camera with some extra randomization.

I'm using the SpriteAnimator, with the simplest Mecanim setup: a single state.

What else can be optimized? I've read something about dropping frames, which could be nice in a crowd, I could drop up to 50% of the frames (30fps compared to 60fps, the default speed of the game).

Is it possible to interpolate the position of the bones by reducing the number of "virtual" keyframes, so that, given an animation, it gets split into, let's say, 12 frames and the rest is just plain interpolation between these 12 states? (I'm not sure this makes sense with the current internal implementation)

Is it still possible to bake animations? I don't want to use sprites :(

Any help about any kind of possible optimizations for a single Spine animations to be played at different speeds on several instances is greatly appreciated.

If something can optimize this, I'm interested in knowing :P

Thank you.
User avatar
NeatWolf
Posts: 66

Pharan

A few ways to optimize things that you need to spawn hundreds of times:
Reduce the number of bones.
Reduce the number of timelines. (eg, if you don't need to move the position, don't key it.)
Reduce the number of verts, or don't use meshes.
Don't use FFD/Deformation.
Don't use PathConstraints or IK.
Use linear graphs on keys instead of curves.
Don't turn attachments on or off, and don't animate draw order; then enable the "Immutable Triangles" option under the Advanced foldout.

Only be as aggressive about it as you need and make sure you don't make false assumptions by actually testing performance on your target device.

Though, really, even 30 Spine Raptors aren't enough to slow down a 7-year old mid-range desktop CPU. So you should check if something else is slowing your game down too.

If all else fails on your target device, you may have to switch to making super simplistic animations in Unity's animation system instead of Spine.

And look into GPU Instancing if you're targeting modern platforms. https://docs.unity3d.com/Manual/GPUInstancing.html
Official Esoteric Assorted Furniture Cleaner and Teahouse | Check out the Spine Users Tumblr Blog: spine-users.tumblr.com
pharan.deviantart.com | pharantriestoanimatestuff.tumblr.com - - - Windows 10 - Spine-Unity.
User avatar
Pharan

Pharan
Posts: 4279

NeatWolf

Pharan wrote:A few ways to optimize things that you need to spawn hundreds of times:
Reduce the number of bones.
Reduce the number of timelines. (eg, if you don't need to move the position, don't key it.)
Reduce the number of verts, or don't use meshes.
Don't use FFD/Deformation.
Don't use PathConstraints or IK.
Use linear graphs on keys instead of curves.
Don't turn attachments on or off, and don't animate draw order; then enable the "Immutable Triangles" option under the Advanced foldout.

Only be as aggressive about it as you need and make sure you don't make false assumptions by actually testing performance on your target device.

Though, really, even 30 Spine Raptors aren't enough to slow down a 7-year old mid-range desktop CPU. So you should check if something else is slowing your game down too.

If all else fails on your target device, you may have to switch to making super simplistic animations in Unity's animation system instead of Spine.

And look into GPU Instancing if you're targeting modern platforms. https://docs.unity3d.com/Manual/GPUInstancing.html
Thanks Pharan!

Sadly, I've already done checked/unchecked everything you mentioned.

I'm on mobile, that's why it is important.

I read something about frame skipping and animation baking.

How can I do that?

Please don't tell me you removed the baking feature as I think I've read it somewhere :(
(is there any way to get it back in that case? I'm pretty sure that could improve performance as well. Any chance I could pay extra to have that feature supported on latest builds?)

Is there anything I can optimize that hasn't been already said? Would enabling GPU instancing help to save some resources on some mobiles, while still being compatible with the ones that don't support it?

Btw: I did some profiling and the Animator.Update and their LateUpdate are eating up to 70% of the total load. And another function that gets called also for animating.

Should I use Animation instead of Animators? I only need 1 animation and sprites simply would require to be way too sharp and detailed to obtain the same result. Also, if the character walks slowly, I should provide at least 120 frames just for the walking cycle, just for a single character style. Way too much memory wasted.

Which implementation is faster, given the same export files? Animators, Animation or...?
Even undocumented unsupported or hacky solutions are welcome.

I'm also culling everything that is not on screen (animator settings)
User avatar
NeatWolf
Posts: 66

Cranktrain

I am using the frame skipping method in my project, it's straightforward to add it around the existing Spine runtime. The joys of having access to the source!

I have a SpineManager class that simply keeps track of the current number of SpineRenderers there are. Every SpineRenderer that gets created knows to update either on an even-numbered frame, or an odd-numbered frame. If it's not it's frame, I just return SkeletonRenderers LateUpdate early.

That's the basic, high-level approach of how I do it, at least.
User avatar
Cranktrain
Posts: 44

NeatWolf

Cranktrain wrote:I am using the frame skipping method in my project, it's straightforward to add it around the existing Spine runtime. The joys of having access to the source!

I have a SpineManager class that simply keeps track of the current number of SpineRenderers there are. Every SpineRenderer that gets created knows to update either on an even-numbered frame, or an odd-numbered frame. If it's not it's frame, I just return SkeletonRenderers LateUpdate early.

That's the basic, high-level approach of how I do it, at least.
Hi, I'm not sure I understood it correctly.

I've read about frameskipping somewhere, as a built-in feature.

So, with this manager, you only do half of the updates per frame. But, don't the animator automatically update themselves? How do you stop them from autoupdating, and how do you force them to update?
User avatar
NeatWolf
Posts: 66

Pharan

Frame skipping isn't a "built-in feature" in the sense that it's just a checkbox in the inspector.
You can implement it in a number of ways though.

Disabling the MonoBehaviours so the lifecycle calls don't automatically get called, and then having your own manager handle update calls is one way though.
Official Esoteric Assorted Furniture Cleaner and Teahouse | Check out the Spine Users Tumblr Blog: spine-users.tumblr.com
pharan.deviantart.com | pharantriestoanimatestuff.tumblr.com - - - Windows 10 - Spine-Unity.
User avatar
Pharan

Pharan
Posts: 4279

NeatWolf

Pharan wrote:Frame skipping isn't a "built-in feature" in the sense that it's just a checkbox in the inspector.
You can implement it in a number of ways though.

Disabling the MonoBehaviours so the lifecycle calls don't automatically get called, and then having your own manager handle update calls is one way though.
Thanks!

Which methods should I be manually calling (if they're public of course) using a SkeletonAnimator?
The profiler is suggesting much of the CPU load is due to the animators Update and LateUpdate.
Having a 30fps crowd on a 60 fps mobile game and halving the cpu load would be great.

What about baking animations?
I bought the Spine2Unity asset from the UAS but it destroys the source atlases, doesn't correctly handle premultiplied alpha and doesn't support skin selection before baking :/
User avatar
NeatWolf
Posts: 66

Pharan

The custom SkeletonAnimation updater would look something like this: https://gist.github.com/pharan/f5a58df99b6ed922c6916428990dcc12
I've set the default to 24fps. See the code.

If you want to try Spine-Unity baking, you can open the SkeletonDataAssetInspector.cs file and uncomment #define SPINE_BAKING near the top. That will show baking options in your SkeletonData assets inspector.

Though I can't imagine why Spine2Unity breaks that stuff. That's terrible about it tampering with source assets though.
Official Esoteric Assorted Furniture Cleaner and Teahouse | Check out the Spine Users Tumblr Blog: spine-users.tumblr.com
pharan.deviantart.com | pharantriestoanimatestuff.tumblr.com - - - Windows 10 - Spine-Unity.
User avatar
Pharan

Pharan
Posts: 4279

NeatWolf

Pharan wrote:The custom SkeletonAnimation updater would look something like this: https://gist.github.com/pharan/f5a58df99b6ed922c6916428990dcc12
I've set the default to 24fps. See the code.

If you want to try Spine-Unity baking, you can open the SkeletonDataAssetInspector.cs file and uncomment #define SPINE_BAKING near the top. That will show baking options in your SkeletonData assets inspector.

Though I can't imagine why Spine2Unity breaks that stuff. That's terrible about it tampering with source assets though.
Well, it messed the alpha of the source textures and they weren't going to work anymore with the premultiplied alpha shader. I'm going to contact the dev as soon as I've got some time.

I'm using a SkeletonAnimator, would frame skipping work with that as well?

After the baking, can I retain the alphapremultiplied shader on the baked object?
(just curious, why has the baking feature been removed?)
User avatar
NeatWolf
Posts: 66

Pharan

Untested SkeletonAnimator version. Should be simple enough to understand if you read the code:
using UnityEngine;
using System.Collections.Generic;

namespace Spine.Unity.Examples {
public class SampleManualUpdator : MonoBehaviour {

[Range(0f, 1/8f)]
[Tooltip("To specify a framerate, type 1/framerate in the inspector text box.")]
public float timeBetweenFrames = 1f/24f; //24 fps
public List<SkeletonAnimator> components;

float accumulator;
bool doLateUpdate;

void OnValidate () {
if (timeBetweenFrames < 0)
timeBetweenFrames = 0;
}

void Start () {
for (int i = 0, n = components.Count; i < n; i++) {
var skeletonAnimator = components[i];
skeletonAnimator.Initialize(false);
skeletonAnimator.clearStateOnDisable = false;
skeletonAnimator.enabled = false;
skeletonAnimator.Update();
skeletonAnimator.LateUpdate();
}
}

void Update () {
if (timeBetweenFrames <= 0) return;
accumulator += Time.deltaTime;

bool doUpdate = false;
if (accumulator > timeBetweenFrames) {
accumulator = accumulator % timeBetweenFrames;
doUpdate = true;
}

if (doUpdate) {
for (int i = 0, n = components.Count; i < n; i++)
components[i].Update(); // Apply Mecanim state

doLateUpdate = true;
}
}

void LateUpdate () {
if (doLateUpdate) {
for (int i = 0, n = components.Count; i < n; i++)
components[i].LateUpdate(); // Generate Mesh

doLateUpdate = false;
}
}
}

}
Spine2Unity is doing something wrong. There's really no reason it needs to tamper with the texture or shaders.
It should work just fine. You use whatever shader and export settings you want as long as they match.

Baking was just removed from the inspector. It was confusing beginners, thinking they needed to use it for basic uses. Especially non-English speakers. And it's just a good idea to make the inspector a bit more tidy instead of having too much extra stuff.

We're thinking of making a new editor window for it so it can be more convenient. Though for now, if you're advanced enough to need baking and know its limitations and what it's for, uncommenting a C# define shouldn't be a problem.
Official Esoteric Assorted Furniture Cleaner and Teahouse | Check out the Spine Users Tumblr Blog: spine-users.tumblr.com
pharan.deviantart.com | pharantriestoanimatestuff.tumblr.com - - - Windows 10 - Spine-Unity.
User avatar
Pharan

Pharan
Posts: 4279

NeatWolf

Pharan wrote:Untested SkeletonAnimator version. Should be simple enough to understand if you read the code:
using UnityEngine;
using System.Collections.Generic;

namespace Spine.Unity.Examples {
public class SampleManualUpdator : MonoBehaviour {

[Range(0f, 1/8f)]
[Tooltip("To specify a framerate, type 1/framerate in the inspector text box.")]
public float timeBetweenFrames = 1f/24f; //24 fps
public List<SkeletonAnimator> components;

float accumulator;
bool doLateUpdate;

void OnValidate () {
if (timeBetweenFrames < 0)
timeBetweenFrames = 0;
}

void Start () {
for (int i = 0, n = components.Count; i < n; i++) {
var skeletonAnimator = components[i];
skeletonAnimator.Initialize(false);
skeletonAnimator.clearStateOnDisable = false;
skeletonAnimator.enabled = false;
skeletonAnimator.Update();
skeletonAnimator.LateUpdate();
}
}

void Update () {
if (timeBetweenFrames <= 0) return;
accumulator += Time.deltaTime;

bool doUpdate = false;
if (accumulator > timeBetweenFrames) {
accumulator = accumulator % timeBetweenFrames;
doUpdate = true;
}

if (doUpdate) {
for (int i = 0, n = components.Count; i < n; i++)
components[i].Update(); // Apply Mecanim state

doLateUpdate = true;
}
}

void LateUpdate () {
if (doLateUpdate) {
for (int i = 0, n = components.Count; i < n; i++)
components[i].LateUpdate(); // Generate Mesh

doLateUpdate = false;
}
}
}

}
Spine2Unity is doing something wrong. There's really no reason it needs to tamper with the texture or shaders.
It should work just fine. You use whatever shader and export settings you want as long as they match.

Baking was just removed from the inspector. It was confusing beginners, thinking they needed to use it for basic uses. Especially non-English speakers. And it's just a good idea to make the inspector a bit more tidy instead of having too much extra stuff.

We're thinking of making a new editor window for it so it can be more convenient. Though for now, if you're advanced enough to need baking and know its limitations and what it's for, uncommenting a C# define shouldn't be a problem.
Thank you very much Pharan!
I will give it a try asap!

Even if I suspect that baking the anims would be probably even faster. I'll do some benchmarking as soon as possible :)
User avatar
NeatWolf
Posts: 66

Pharan

It probably will be, as long as all those keys were linear.
Official Esoteric Assorted Furniture Cleaner and Teahouse | Check out the Spine Users Tumblr Blog: spine-users.tumblr.com
pharan.deviantart.com | pharantriestoanimatestuff.tumblr.com - - - Windows 10 - Spine-Unity.
User avatar
Pharan

Pharan
Posts: 4279

NeatWolf

Pharan wrote:It probably will be, as long as all those keys were linear.
Hi @Pharan,

I'm not sure about what you mean.

Did you mean that the linear tweens are faster (which I think could be always true in general), or are you implicitly suggesting that baking non linear keys will result in animations that are even slower than they're supposed to be?

By the way, I still haven't done any baking with such complex animations. Do baked anims support time stretching (playing at a different speed) and deformations? I'm not sure about the output.

Do Unity quality settings about bones and interpolation somehow interfer with Spine or they're totally a world apart?
User avatar
NeatWolf
Posts: 66


Return to Unity