- تم التحرير
Animation w/ asset change cause asset to vanish on skinchang
We have an animation that causes an asset change. When asset swaps are keyframed in the editor:
asset.json
"DANCING-ACTIVE": {
"slots": {
"hand-left": {
"attachment": [
{ "time": 0, "name": "hand-left" },
{ "time": 0.3333, "name": "hand-left-wide" },
{ "time": 1, "name": "hand-left-wide" },
{ "time": 1.6667, "name": "hand-left-wide" },
{ "time": 1.7667, "name": "hand-left" }
]
},
For some reason, all asset changes work just fine when a skin is applied that refers to these assets, e.g.
code.js
skeleton.setSkinByName('baseskin")
asset.json
// .skins.baseskin.
"hand-left": {
"hand-left": {
"name": "base-skin-medium/hand-left",
"path": "hayleigh/hand-left",
"x": 29.39,
"y": 1.02,
"rotation": 84.61,
"width": 56,
"height": 83
},
"hand-left-closed": {
"name": "base-skin-medium/hand-left-closed",
"path": "hayleigh/hand-left-closed",
"x": 20.13,
"y": -2.45,
"rotation": 88.82,
"width": 60,
"height": 65
},
"hand-left-wide": {
"name": "base-skin-medium/hand-left-wide",
"path": "hayleigh/hand-left-wide",
"x": 27.68,
"y": 1.62,
"rotation": 88.82,
"width": 85,
"height": 81
}
},
However, if we swap to a skin that doesn't point to these assets at all, suddenly the (in this case hand) skin vanishes:
code.js
skeleton.setSkinByName('brows-large');
assset.json
// skins.
"brows-large": {
"brow-left": {
"brow-left": {
"name": "brows-large/brow-left",
"path": "gerald/brow-left",
"x": 21.54,
"y": -3.89,
"rotation": 165.3,
"width": 88,
"height": 34
}
},
"brow-right": {
"brow-right": {
"name": "brows-large/brow-right",
"path": "gerald/brow-right",
"x": 17.97,
"y": 1.63,
"rotation": 15.52,
"width": 54,
"height": 29
}
},
"hip-clothing-path": {
"hip-clothing-path": {
"type": "path",
"lengths": [ 91.59, 193.16, 413.79 ],
"vertexCount": 9,
"vertices": [ 1, 117, -29.1, -0.42, 1, 1, 117, -1.63, 0.28, 1, 1, 117, 11.16, 0.6, 1, 2, 117, 61.08, 0.45, 0.5, 118, -28.82, 0.47, 0.5, 2, 117, 89.94, 0.46, 0.5, 118, 0.04, 0.49, 0.5, 2, 117, 118.79, 0.47, 0.5, 118, 28.89, 0.52, 0.5, 1, 118, 76.84, 0.62, 1, 1, 118, 101.58, -0.04, 1, 1, 117, 221.76, -0.16, 1 ]
}
},
"leg-left-path": {
"leg-left-path": {
"type": "path",
"lengths": [ 135.63, 254.42, 545.47 ],
"vertexCount": 9,
"vertices": [ 1, 36, -22.4, 2.79, 1, 1, 36, 14.25, 1.58, 1, 1, 36, 58.02, 0.14, 1, 2, 36, 101.57, 2.59, 0.5, 37, -18.68, 2.51, 0.5, 2, 36, 139.73, 2.27, 0.5, 37, 19.48, 2.19, 0.5, 2, 36, 177.89, 1.95, 0.5, 37, 57.64, 1.86, 0.5, 1, 37, 85.55, 0.15, 1, 1, 37, 128.11, -0.37, 1, 1, 36, 308.29, -1.33, 1 ]
}
},
"leg-right-path": {
"leg-right-path": {
"type": "path",
"lengths": [ 151.09, 275.75, 588.49 ],
"vertexCount": 9,
"vertices": [ 1, 49, -37.7, -0.53, 1, 1, 49, -0.69, -0.46, 1, 1, 49, 57.08, -0.36, 1, 2, 49, 112.59, 1, 0.5, 51, -27.26, 0.89, 0.5, 2, 49, 150.13, -0.02, 0.5, 51, 10.27, -0.18, 0.5, 2, 49, 186.36, -1.02, 0.5, 51, 46.51, -1.21, 0.5, 1, 51, 110.63, -1.86, 1, 1, 51, 134.65, -2.05, 1, 1, 49, 320.75, -1.52, 1 ]
}
}
},
How can we work around this? We'd like the assets to not disappear like this.
Posting here (instead of via email) to share the code with everyone.
The solution is to create a combined skin programmatically, consisting of a base skin (providing the full set) and additive partial equipment skins (overriding only some attachments, but not all).
You can take the following Unity C# code as an example, it also covers removal of skins (sorry that it's C#, but I'm sure you can come up with a js equivalent easily):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Spine.Unity.Modules.AttachmentTools;
public class EquipPartialSkinDemo : MonoBehaviour {
Spine.Unity.SkeletonAnimation skeletonAnimation;
Spine.Skin templateBaseSkin;
List<Spine.Skin> addedPartialSkins = new List<Spine.Skin>();
Spine.Skin combinedSkin;
void Awake() {
skeletonAnimation = this.GetComponent<Spine.Unity.SkeletonAnimation>();
combinedSkin = new Spine.Skin("CombinedSkin");
}
IEnumerator Start() {
EquipBaseSkin("full-gerald");
yield return new WaitForSeconds(3);
Debug.Log("adding brows-large");
EquipPartialSkin("brows-large");
yield return new WaitForSeconds(3);
Debug.Log("removing brows-large");
UnequipPartialSkin("brows-large");
}
void EquipBaseSkin(string skinName) {
templateBaseSkin = skeletonAnimation.Skeleton.Data.FindSkin(skinName);
RefreshSkin();
}
void EquipPartialSkin(string skinName) {
var templatePartialSkin = skeletonAnimation.Skeleton.Data.FindSkin(skinName);
if (templatePartialSkin != null)
addedPartialSkins.Add(templatePartialSkin);
RefreshSkin();
}
void UnequipPartialSkin(string skinName) {
for (int i = 0; i < addedPartialSkins.Count; ++i) {
if (addedPartialSkins[i].Name == skinName) {
addedPartialSkins.RemoveAt(i);
break;
}
}
RefreshSkin();
}
void RefreshSkin() {
RecombineSkin();
skeletonAnimation.Skeleton.Skin = combinedSkin;
RefreshSkeletonAttachments();
}
void RecombineSkin() {
combinedSkin = new Spine.Skin("CombinedSkin");
combinedSkin.AddAttachments(templateBaseSkin);
foreach (var partialSkin in addedPartialSkins) {
combinedSkin.AddAttachments(partialSkin);
}
}
void RefreshSkeletonAttachments() {
skeletonAnimation.Skeleton.SetSlotsToSetupPose();
skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton);
}
}