Hey,
We have a couple of helmets for our characters. The helmets share a skin-placeholder, but some helmets also have a light that is assigned to that skin. In the Spine Editor when pinning a helmet, then another one and unpinning the previous one, it behaves as we expect, the placeholder is replaced, and the extra light attachment is turned off.

In unity the extra attachment lingers around, the stuff in the placeholders is replaced, but the light would just stay visible, even though the skin was removed from the newly applied mixAndMatch skin.

We can fix this by adding every single skin attachment to their own skin placeholder, but this would require a lot of extra work. Do I need to refresh or update anything additionally in Unity?

internal void SetSkin(string skinName)
{
    m_activeSkinList.Add(skinName);
    UpdateSkin();
}

internal void RemoveSkin(string skinName)
{
    m_activeSkinList.Remove(skinName);
    UpdateSkin();
}

internal void UpdateSkin()
{
    var skeleton = m_skeletonAnimation.Skeleton;
    var skeletonData = skeleton.Data;
    var mixAndMatchSkin = new Skin("skin_match");
    for (int i = 0; i < m_activeSkinList.Count; i++)
    {
        Skin skin = skeletonData.FindSkin(m_activeSkinList[i]);
        if (skin != null)
            mixAndMatchSkin.AddSkin(skin);
    }
    skeleton.SetSkin(mixAndMatchSkin);
    skeleton.SetSlotsToSetupPose();
    m_skeletonAnimation.AnimationState.Apply(m_skeletonAnimation.Skeleton);
    ColorTeam();
}

Thank you!

Related Discussions
...

The issue you're encountering is due to the way skins and attachments are managed in Unity. When you set a new skin, the attachments from the previous skin are not automatically removed unless explicitly handled. This behavior is by design to allow flexibility, but it can lead to lingering attachments as you've described.

To resolve this, you can modify your UpdateSkin method to clear the attachments before setting the new skin. Here's an updated version of your method:

internal void UpdateSkin()
{
    var skeleton = m_skeletonAnimation.Skeleton;
    var skeletonData = skeleton.Data;
    var mixAndMatchSkin = new Skin("skin_match");

    // Clear existing attachments
    foreach (var slot in skeleton.Slots)
    {
        slot.Attachment = null;
    }

    // Add skins to the mixAndMatchSkin
    for (int i = 0; i < m_activeSkinList.Count; i++)
    {
        Skin skin = skeletonData.FindSkin(m_activeSkinList[i]);
        if (skin != null)
            mixAndMatchSkin.AddSkin(skin);
    }

    skeleton.SetSkin(mixAndMatchSkin);
    skeleton.SetSlotsToSetupPose();
    m_skeletonAnimation.AnimationState.Apply(m_skeletonAnimation.Skeleton);
    ColorTeam();
}

This code ensures that all attachments are cleared before applying the new skin, which should prevent any lingering attachments from previous skins.

Additionally, you can refer to the spine-unity Mix and Match documentation for more details on handling skins and attachments programmatically.

@paatz04 Normally you don't need to clear all slots manually as above for newly set skins, what you normally do is let the SetSlotsToSetupPose call set the slot attachments to null or not according to the setup pose.

Also see the documentation here (which I assume you're already familiar with):
http://esotericsoftware.com/spine-api-reference#Skeleton-setSkin

What does ColorTeam(); do?
It sounds a bit as if the problem comes from somewhere else than from the code shown above, or can you also reproduce this behaviour with just the lines above, without calling additional methods like ColorTeam();?