2019-11-20 Unity中Spine動(dòng)態(tài)局部換裝實(shí)現(xiàn)方案

以下分享僅基于目前個(gè)人所知的經(jīng)驗(yàn)總結(jié),如有錯(cuò)誤歡迎指正

【思路】

在Unity中的Spine實(shí)現(xiàn)局部換裝的方式有很多種,如

1、使用Sprite動(dòng)態(tài)替換Attachment

2、在Spine文件中提前預(yù)設(shè)好各個(gè)Slot的Attachment,在運(yùn)行時(shí)使用代碼直接切換具體Slot下對(duì)應(yīng)的Attachment

3、動(dòng)態(tài)組裝新的皮膚套用到Spine角色上

這里舉例的是第三種方式

【原理】

Spine元素主要包含皮膚(Skin)、骨骼(Bone)、插槽(Slot)、附件(Attachment)、及附件下的圖片

而皮膚(Skin)包含了插槽信息、附件信息,如果我們有兩套相同構(gòu)成的皮膚,原理上就可以通過拼裝皮膚上的插槽實(shí)現(xiàn)局部換膚功能

【實(shí)現(xiàn)方式】

代碼:

using Spine;
using Spine.Unity;
using UnityEngine;

public class DynamicChangeSkin: MonoBehaviour
{
    public SkeletonAnimation targetSkeleton;
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            string slotName = "YourSlotName";
            string skinName = "YourSkinName";
            SkeletonData skeletonData = targetSkeleton.SkeletonDataAsset.GetSkeletonData(false);
            Skin skin = skeletonData.FindSkin(skinName);
            int slotIndex = skeletonData.FindSlotIndex(slotName);
            ChangeAttachment(slotName, GetAttachmentFromSkin(skin, slotIndex, slotName));
        }
    }

    public Attachment GetAttachmentFromSkin(Skin skin, int slotIndex, string slotName)
    {
        return skin.GetAttachment(slotIndex, slotName);
    }

    /// <summary>
    /// 傳入的是新部件所在皮膚的Attachment
    /// </summary>
    /// <param name="slotName"></param>
    /// <param name="attachment"></param>
    public void ChangeAttachment(string targetSlotName, Attachment attachment)
    {
        if (attachment == null)
        {
            Debug.LogWarning("GetAttachmentFromSkin() return , attachment == null");
        }
        //  遍歷targetSkeleton所有slot,創(chuàng)建新皮膚
        Skin newSkin = new Skin("NewSkin");
        foreach (var item in targetSkeleton.skeleton.Slots)
        {
            string slotName = item.ToString();
            int slotIndex = item.Skeleton.FindSlotIndex(slotName);
            Attachment tempAttackment = null;
            if (slotName.Equals(targetSlotName))
            {
                tempAttackment = attachment;
                Debug.LogWarning("Replace slotIndex: " + slotIndex + ", slotName: " + slotName);
            }
            else
            {
                tempAttackment = item.Attachment;
            }
            Skin.SkinEntry entry = new Skin.SkinEntry(slotIndex, slotName, tempAttackment);
            newSkin.Attachments.Add(entry, tempAttackment);
            Debug.Log("slotIndex: " + slotIndex + ", slotName: " + slotName);
        }
        targetSkeleton.skeleton.SetSkin(newSkin);
    }
}

同時(shí)修改多個(gè)slot的方法

using Spine;
using Spine.Unity;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class DynamicChangeSkin: MonoBehaviour
{
    public SkeletonAnimation targetSkeleton;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.T))
        {
            string skinName = "YourSkinName";
            List<string> slotNames = new List<string>();
            slotNames.Add("YourSlotName1");
            slotNames.Add("YourSlotName2");
            slotNames.Add("YourSlotName3");
            ChangePartSkin(skinName, slotNames);
        }
    }

    private void ChangePartSkin(string skinName, List<string> slotNames)
    {
        SkeletonData skeletonData = targetSkeleton.SkeletonDataAsset.GetSkeletonData(false);
        Skin skin = skeletonData.FindSkin(skinName);
        Dictionary<string, Attachment> slotAttachmentDic = new Dictionary<string, Attachment>();
        for (int i = 0; i < slotNames.Count; i++)
        {
            string slotName = slotNames[i];
            int slotIndex = skeletonData.FindSlotIndex(slotName);
            slotAttachmentDic.Add(slotName, skin.GetAttachment(slotIndex, slotName));
        }
        ApplyNewSkinFromPartAttachment(slotAttachmentDic);
    }

    /// <summary>
    /// 傳入的是新部件所在皮膚的Attachment
    /// </summary>
    /// <param name="slotName"></param>
    /// <param name="attachment"></param>
    public void ApplyNewSkinFromPartAttachment(Dictionary<string, Attachment> slotAttachmentDic)
    {
        //  遍歷targetSkeleton所有slot,創(chuàng)建新皮膚
        Skin newSkin = new Skin("NewSkin");
        foreach (var item in targetSkeleton.skeleton.Slots)
        {
            string slotName = item.ToString();
            int slotIndex = item.Skeleton.FindSlotIndex(slotName);
            Attachment tempAttackment = null;
            if (slotAttachmentDic.ContainsKey(slotName))
            {
                tempAttackment = slotAttachmentDic[slotName];
            }
            else
            {
                tempAttackment = item.Attachment;
            }
            Skin.SkinEntry entry = new Skin.SkinEntry(slotIndex, slotName, tempAttackment);
            newSkin.Attachments.Add(entry, tempAttackment);
            Debug.Log("slotIndex: " + slotIndex + ", slotName: " + slotName);
        }
        targetSkeleton.skeleton.SetSkin(newSkin);

    }

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容