• Runtimes
  • Animation w/ asset change cause asset to vanish on skinchang

  • تم التحرير
Related Discussions
...

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.

6 أيام لاحقا

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);
   }
}