If you plan to have 100 of that skeleton, the first step is to massively simplify the skeleton's setup. Only have the minimum number of bones and attachments, and in the animations, a minimum number of animated properties. And make sure each instance only uses one material.
Next, if you don't mind some or the rest of the instances to be using the exact same pose, the other instances can just be mirrored from an original SkeletonAnimation using MeshFilter+MeshRenderer GameObjects without actual Spine components on it.
The component on the Spine GameObject would look like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshRenderer), typeof(MeshFilter))]
public class MeshMirror : MonoBehaviour {
public MeshFilter[] meshFilters = new MeshFilter[1];
MeshFilter sourceMeshFilter;
void Awake () {
sourceMeshFilter = GetComponent<MeshFilter>();
var sourceRenderer = GetComponent<MeshRenderer>();
if (sourceRenderer == null) return;
var sourceMaterials = sourceRenderer.sharedMaterials;
foreach (var m in meshFilters) {
var mr = m.GetComponent<MeshRenderer>();
mr.sharedMaterials = sourceMaterials;
// Copy other properties if you want.
// mr.sortingOrder = sourceRenderer.sortingOrder;
// mr.sortingLayerID = sourceRenderer.sortingLayerID;
// mr.receiveShadows = sourceRenderer.receiveShadows;
// mr.shadowCastingMode = sourceRenderer.shadowCastingMode;
// mr.motionVectorGenerationMode = sourceRenderer.motionVectorGenerationMode;
}
}
void LateUpdate () {
// Spine Requires this update every frame because it uses double-buffering.
var mfs = meshFilters;
var sourceMesh = sourceMeshFilter.sharedMesh;
for (int i = 0, n = meshFilters.Length; i < n; i++) {
mfs[i].sharedMesh = sourceMesh;
}
}
}
The mirroring GameObjects should look like this
Thirdly, you can randomize and stagger their updates if they have to move independently of each other.
To do that, you disable the SkeletonAnimation, and call its Update and LateUpdate in your own script whenever you want.
IEnumerator StaggerUpdate () {
while (true) {
skeletonAnimation.Update();
// assuming you don't do anything between here.
skeletonAnimation.LateUpdate();
yield return null;
// skip one frame, for example.
yield return null;
}
yield return null;
}