• Editor
  • Can you convert animation curves to multiple keyframes?

Related Discussions
...

Hi. Can you convert animation curves to multiple keyframes when export binary or json?
I think, it will increase memory size, but it will improve the performance of our game.
Please consider it. 🙂

The process you refer to is called baking. Before undertaking any kind of "optimization" it's good practice to verify that the thing you want to optimize is actually the bottle neck. What engine and Spine runtime are you using? How are your skeletons setup (number of attachments, timelines, keys, etc.)? Did you profile your game? Can you provide us with a sample that reproduces the performance issues?

You may also have a lot of unnecessary animation dopesheet items if it's actually affecting your performance.
Back up your project and try the Clean Up button when you have an animation selected: Animation clean up

Note the benefits:

  1. A cleaner dopesheet so you understand what's actually changing.
  2. Fewer stuff for the runtime to crunch, so it costs less performance to have more and more of your characters/skeletons at any time.

When not to use it:

  1. If you have a multi-track animation setup, and you specifically keyed certain bones to override the movement of bones, and parts of the override pose happen to be setup pose.
  2. If you added timelines with only setup-pose keys for any deliberate reason.
  3. If you added more than 2 keys repeating the same value/pose for any deliberate reason.

Thank you for your advices!
I develop mobile app with unity 2018.1 and latest spine-unity 3.6 runtime.
I'm sorry, I am prohibited to share our products. I took a screen shot.

I made a test on iPodTouch 6th generation.

I put 100 skeletons in scene. (at 3448 fps)
I made a clone and edited json to change curve to linear. (at 3852 fps)
I removed 3 unnecessary timeline from original json.(at 3753 fps)
I changed curve to linear. (at 4155 fps)

And I profiled this test.
CurveTimeline.GetCurvePercent took 1.5%4% of CPU Time.

I think it's not actually the bottle neck, but I was able to improve the performance a little.
Thank you!

Thanks for the data!
Observable improvement though.

In this case where you have to spawn 100 of the same skeleton in the scene in Unity, using "Skeleton Baker" might be a good option.
You can find Skeleton Baking window by selecting your SkeletonDataAsset and right-clicking the top of its inspector (or clicking on the gear icon) and choosing "Skeleton Baking". This window allows you to convert your SkeletonData into a Unity prefab and UnityEngine animation clips. Unity's native animation system may give you some performance benefits when there's that many skeletons.
Note that Unity's animation system doesn't support all of Spine's features so some things like. Mesh deformation, animated colors and draw order will not work.

Sounds great! I'll try it.
Thank you! 🙂

If your skeletons are all the same skeleton data and you don't need all 100 skeletons to be animated independently, you could have some smaller number of skeletons and animation states (eg 10) and draw those skeletons multiple times. If it is a crowd of 100 skeletons, users probably wouldn't notice that some of the skeletons are synchronized. Even if you used 1 skeleton for every 2 on-screen, you'd have half as many animation states to apply.

In Unity, Nate's suggestion as a Component would look something like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class MeshRenderCopier : MonoBehaviour {

   public MeshRenderer sourceRenderer;

   MeshFilter sourceMeshFilter;
   MeshRenderer meshRenderer;
   MeshFilter meshFilter;

   void Awake () {
      meshRenderer = this.GetComponent<MeshRenderer>();
      meshFilter = this.GetComponent<MeshFilter>();

  if (sourceRenderer != null)
     sourceMeshFilter = sourceRenderer.GetComponent<MeshFilter>();
   }

   void LateUpdate () {
      //if (sourceRenderer == null) return;
      meshRenderer.sharedMaterial = sourceRenderer.sharedMaterial; // Assumes there is only one material. If your material doesn't change every frame, you may see better performance if you skip this.
      meshFilter.sharedMesh = sourceMeshFilter.sharedMesh;
   }

}

This can also be done by a more centralized component that handles copying from multiple sources to multiple receiving renderers.

Thank you for your further advice!
I implemented the technique and our game performance was considerably improved!!
I am grateful for your support! 🙂