• Unity
  • SkeletonGraphic rendering issue.

We are having problems with Attachments on our animations in when used on a canvas (using a SkeletonGraphic)

We have a Spine Skeleton Animation in-game that has an attachment slot called Toys/Ball, when the Skeleton Animation has no ball then the attachment slot is removed, if a ball is attached then the attachment slot sprite gets remapped with the correct item sprite.

We also have a Spine Skeleton Graphic with the same skeleton data as the Skeleton animation so we can use it in the UI.

The issue is that when a ball is attached to the Skeleton Animation is has the intended effect, but when the Skeleton Graphic is displayed it seems all of the attachment slot sprites are using the Ball sprite

Here's the code we're using:

protected const string ToyAttachSlot = "ToyAttach";    //  the name of the attachment slot
protected const string ToyAttachName = "Toys/Ball";    //  the name of the ball attachment that we want to replace.

public virtual void SetAnimationItem(Sprite sprite)
{
    _dogSkeletonComponent.SkeletonDataAsset?.atlasAssets[0].PrimaryMaterial.Equals(_animationMaterial);
    _toySlotIndex = SkeletonInstance.FindSlotIndex(ToyAttachSlot);
    //  Search for the default skin
    Skin defaultSkin = _dogSkeletonComponent.SkeletonDataAsset.GetSkeletonData(false).DefaultSkin;
    //  the default skin has the attachment to clone
    Attachment toyAttach = defaultSkin.GetAttachment(_toySlotIndex, ToyAttachName);
    //  clone the attachment.  When the skeleton is reloaded, it will have this toy attached
    try
    {
        _toyAttach = toyAttach.GetRemappedClone(sprite, _animationMaterial);
        Debug.Log($"<color=cyan>Dog item attached: {sprite.name}</color>");
    }
    catch (NullReferenceException nrex)
    {
        Debug.LogError($"Unable to find Animation Toy AttachPoint for {_dogSkeletonComponent.SkeletonDataAsset.name}");
    }

ReloadSkeleton();
}

public virtual void ReloadSkeleton()
{
    try
    {
        //Debug.Log($"<color=cyan>Reloading Skin</color>");
        Skin mixAndMatchSkin = new Skin("Mixed");
        SkeletonDataAsset skeletonDataAsset = _dogSkeletonComponent?.SkeletonDataAsset;
        //    search for the skin parts
        foreach (Skin skin in skeletonDataAsset.GetSkeletonData(false).Skins)
        {
            if (_dog.SkinNames.Contains(skin.Name))
            {
                if (_toySlotIndex > 0)
                {
                    //  remove any existing attachment from this slot
                    skin.RemoveAttachment(_toySlotIndex, ToyAttachName);

                if (_toyAttach != null)
                {
                    //  attach the new one.
                    skin.SetAttachment(_toySlotIndex, ToyAttachName, _toyAttach);
                }
            }
            mixAndMatchSkin.AddSkin(skin);
        }
    }

    SkeletonInstance.SetSkin(mixAndMatchSkin);

    //  these steps are recommended when attaching objects.
    SkeletonInstance.SetSlotsToSetupPose();
    SkeletonInstance.Update(0);
}
catch (Exception ex)
{
    Debug.LogException(ex);
}
}

When we Render the dog without an attachment it works fine in both a SkeletonAnimation (in world)

and a SkeletonGraphic (in Canvas) object:

Our problem is that when we add an attachment (in this case a ball) to the animation, it screws up the material mapping in the SkeletonGraphic canvas renderer.

It looks fine in the SkeletonAnimation (in world):

but the SkeletonGraphic (in Canvas) has the ball material entirely overwriting the whole animated character material:

We have dug around looking at the Debug inspector attributes for the SkeletonGraphic, and we can see that the Base Texture is getting overwritten by the attachment sprite:
Pre-Attachment:

Post-Attachment

This doesn't happen for the SkeletonAnimation object.

Can anyone suggest what we are doing wrong? Is there anything in our code that looks wrong, or is this a problem within Spine?

We currently are using Unity 2019.3.0f6, and the latest build of Spine (spine-unity-3.8-2020-02-26).

We have recently updated to using URP in Unity, and the new spine shaders to support this, but we have had the same issue for quite some time (at least since using spine 3.7 and older versions of Unity)

Related Discussions
...

We are sorry for the inconvenience and thanks for your detailled writeup.

As described on the spine-unity documentation pages here:

Important Note: due to limitations of the used Unity CanvasRenderer, SkeletonGraphic is limited to a single texture. This means Skeletons used in UI have to be packed as a single-texture (single-page) atlas, rather than multi-page atlases.
See section [Advanced - Export for SkeletonGraphic](http://esotericsoftware.com/spine-unity#Advanced


Export-for-SkeletonGraphic) for a possible workarounds to this limitation.

In your case we would suggest to repack all attachments at runtime to a single atlas page. You can have a look at the Mix and Match and Mix and Match example scenes in the Spine Examples/Other Examples directory that comes with the spine-unity unitypackage. Especially the MixAndMatchGraphic.cs script should be helpful as reference.

We are working on a workaround to support multiple atlas pages:
[unity] Support multiple atlas textures at SkeletonGraphic · #1592

4 days later

Thanks for that, I'll take a look at implementing something like that.