• Unity
  • Mix&Match HELP!

Related Discussions
...

Hi,
I'm a beginner for Spine,I'm testing for character equips.I modify the scripts from Mix And Match Equip, and the attachment was replaced successfully when i swapped items , but there was a problem and I can't find why,when i created Repacked Skin,the sprite of attachments of the SkeletonGraphic except i swapped disappeared.

Before equipped:

After equipped:

here is my code:

public class EquipInterface : MonoBehaviour
    {
        [SpineSkin]
        public string templateSkinName;
        public Material templateMaterial;
        public SkeletonDataAsset skeletonDataAsset;

    [Header("Repacked")]
    public Material runtimeMaterial;
    public Texture2D runtimeAtlas;

    protected Spine.Skin equipsSkin;
    protected Spine.Skin collectedSkin;
    protected Material source_materail;

    /// <summary>
    /// 根据attachment名字和sprite映射的attachment缓存
    /// </summary>
    protected Dictionary<string, Dictionary<Sprite, Attachment>> Cache_Attachment_Map = new Dictionary<string, Dictionary<Sprite, Attachment>>();

    protected virtual void Init() { }
    protected virtual Attachment GetAndCacheAttachment(int slot_idx, string attach_name,Sprite attach_sprite)
    {
        Attachment temp_attachment = null;
        Dictionary<Sprite, Attachment> sprite_attach_map = null;
        Cache_Attachment_Map.TryGetValue(attach_name, out sprite_attach_map);
        if (sprite_attach_map == null)
        {
            sprite_attach_map = new Dictionary<Sprite, Attachment>();
            Cache_Attachment_Map.Add(attach_name, sprite_attach_map);
        }
        sprite_attach_map.TryGetValue(attach_sprite, out temp_attachment);
        if (temp_attachment == null)
        {
            var skeletonData = skeletonDataAsset.GetSkeletonData(true);
            var templateSkin = skeletonData.FindSkin(templateSkinName);
            Attachment templateAttachment = templateSkin.GetAttachment(slot_idx, attach_name);
            temp_attachment = templateAttachment.GetRemappedClone(attach_sprite, templateMaterial, true,true,true);
            sprite_attach_map.Add(attach_sprite, temp_attachment);
        }
        return temp_attachment;
    }

    public virtual void Equip(int slotIndex, string attachmentName, Sprite attachSprite) { }
    public virtual void OptimizeSkin() { }
    public virtual void RefreshSkeletonAttachments() { }
}

public class SkeletonGraphicInterface : EquipInterface
    {
        public SkeletonGraphic skeletonGraphic;

    protected override void Init()
    {
        if (equipsSkin != null)
            return;
        equipsSkin = new Skin("Equips Skin");
        //equipsSkin = skeletonGraphic.Skeleton.UnshareSkin(true, true, skeletonGraphic.AnimationState);
        var templateSkin = skeletonGraphic.Skeleton.Data.FindSkin(templateSkinName);
        if (templateSkin != null)
            equipsSkin.AddAttachments(templateSkin);
        skeletonGraphic.Skeleton.Skin = equipsSkin;
        RefreshSkeletonAttachments();
    }

    public override void Equip(int slotIndex, string attachmentName, Sprite attachSprite)
    {
        var attachment = base.GetAndCacheAttachment(slotIndex, attachmentName, attachSprite);
        if (attachment == null)
        {
            Debug.LogError(string.Format("找不到attachment,插槽index: {0},附件名字: {1},sprite: {2}", slotIndex,attachmentName,attachSprite));
            return;
        }
        Init();
        equipsSkin.AddAttachment(slotIndex, attachmentName, attachment);
        skeletonGraphic.Skeleton.SetSkin(equipsSkin);
        RefreshSkeletonAttachments();
    }

    public override void OptimizeSkin()
    {
        // 1. Collect all the attachments of all active skins.
        collectedSkin = collectedSkin ?? new Skin("Collected skin");
        collectedSkin.Clear();
        collectedSkin.AddAttachments(skeletonGraphic.Skeleton.Data.DefaultSkin);
        collectedSkin.AddAttachments(equipsSkin);

        // 2. Create a repacked skin.
        source_materail = source_materail ?? skeletonGraphic.SkeletonDataAsset.atlasAssets[0].PrimaryMaterial;
        var repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin", source_materail, out runtimeMaterial, out runtimeAtlas);
        collectedSkin.Clear();

        // 3. Use the repacked skin.
        skeletonGraphic.Skeleton.Skin = repackedSkin;
        RefreshSkeletonAttachments();
        skeletonGraphic.OverrideTexture = runtimeAtlas;
    }

    public override void RefreshSkeletonAttachments()
    {
        skeletonGraphic.Skeleton.SetSlotsToSetupPose();
        skeletonGraphic.AnimationState.Apply(skeletonGraphic.Skeleton);//skeletonGraphic.Update(0);
    }
}

the repacked atlas:

My English is poor,any idea?Thx :rofl:


Anybody help?


T T T T

Sorry, I've kicked Pharan and Harri, hopefully they can help you out soon!

Unfortunately I could not reproduce your problem. I created a test setup with your scripts and added the call to OptimizeSkin() as follows:

public override void Equip(int slotIndex, string attachmentName, Sprite attachSprite)
{
   ...
   equipsSkin.AddAttachment(slotIndex, attachmentName, attachment);
   skeletonGraphic.Skeleton.SetSkin(equipsSkin);
   RefreshSkeletonAttachments();

   OptimizeSkin(); // added this call here
}

It created the atlas successfully in my setup.

Could you please create a zipped package of a minimal Unity project that shows this problem and send it to contact@esotericsoftware.com? That would help us a lot in resolving your issue. Thanks and sorry for the delay.

@Nate @[supprimé]
Thank you very much!!! 😃
I had found this problem.
Because of I forgotten ticked the option of "Read/Write Enabled" atlas Spine exported in the Unity 3D.

Glad you could resolve the issue, and thanks for the info - I will see if we can add a check / descriptive error message for that!