以下分享僅基于目前個(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);
}
}