赞
踩
1.Spine元素主要包含皮肤(Skin)、骨骼(Bone)、插槽(Slot)、附件(Attachment)、及附件下的图片。
2.而皮肤(Skin)包含了插槽信息、附件信息,如果我们有两套相同构成的皮肤,原理上就可以通过拼装皮肤上的插槽实现局部换肤功能。
3.创建新的Skin 替换槽点下的附件的Sprite,实现动态换皮。
4.Spine 换皮代码:
using System; using Spine; using Spine.Unity; using Spine.Unity.AttachmentTools; using UnityEngine; /// <summary> /// 换皮测试 /// </summary> public class SpineChangeSkin : MonoBehaviour { private SkeletonAnimation skeletonAnimation; private SkeletonDataAsset skeletonDataAsset; private Material sourceMaterial; private SkeletonData skeletonData; private bool applyPma = true; [SpineSkin] private string templateSkinName;//模板皮肤名称(初始) private Skin equipsSkin; private Skin collectedSkin; #region 优化皮肤用 private Material runtimeMaterial; private Texture2D runtimeAtlas; #endregion #region ChangeShin需要的 外部可显示 选择 //[SpineSlot] public string slot1; //骨骼槽点 //[SpineSkin] public string templateSkin; //[SpineAttachment(skinField: "templateSkin")] //public string templateAttachment; #endregion void Start() { skeletonAnimation = GetComponent<SkeletonAnimation>(); skeletonDataAsset = skeletonAnimation.SkeletonDataAsset; sourceMaterial = skeletonDataAsset.atlasAssets[0].PrimaryMaterial; skeletonData = skeletonAnimation.Skeleton.Data; ReSetSkin(); } private void ReSetSkin() { var skeleton = skeletonAnimation.skeleton; var skin = skeleton.Skin; if (skin == null) templateSkinName = "default"; else templateSkinName = skin.Name; equipsSkin = new Skin("Equips"); var tSkin = skeletonData.FindSkin(templateSkinName); if (tSkin != null) equipsSkin.AddAttachments(tSkin); skeletonAnimation.Skeleton.Skin = equipsSkin; RefreshSkeletonAttachments(); } /// <summary> /// 局部换皮 /// </summary> /// <param name="slot">骨骼槽点昵称</param> /// <param name="attachmentName">SpineAttachment 类型 一般和slot名称相同</param> /// <param name="sprite">要更改的贴图[需要开启读写功能]</param> public void ChangeShin(string slot, string attachmentName,Sprite sprite) { int slotIndex = skeletonData.FindSlot(slot).Index;//根据骨骼槽点 找到槽点索引 Attachment attachment = GenerateAttachment(slotIndex, templateSkinName, attachmentName, sprite); if (attachment == null)return; equipsSkin.SetAttachment(slotIndex, attachmentName, attachment); skeletonAnimation.Skeleton.SetSkin(equipsSkin); RefreshSkeletonAttachments(); OptimizeSkin(); } private Attachment GenerateAttachment(int slotIndex, string tSkinName, string attachmentName,Sprite sprite) { var sData = skeletonDataAsset.GetSkeletonData(true); var tSkin = sData.FindSkin(tSkinName); Attachment tAttachment = tSkin.GetAttachment(slotIndex, attachmentName); if (tAttachment == null) { Debug.LogError($"skin {tSkinName} slotIndex {slotIndex} attachmentName {attachmentName} ==》attachment=null"); return null; } var attachment = tAttachment?.GetRemappedClone(sprite, sourceMaterial, premultiplyAlpha: this.applyPma); return attachment; } /// <summary> /// 刷新皮肤 /// </summary> void RefreshSkeletonAttachments() { skeletonAnimation.Skeleton.SetSlotsToSetupPose(); skeletonAnimation.AnimationState.Apply(skeletonAnimation.Skeleton); //skeletonAnimation.Update(0); } /// <summary> /// 优化皮肤 将换过皮肤的贴图 整合到一张贴图中 [人物贴图需要开启读写功能] /// </summary> public void OptimizeSkin() { try { // 1. 收集所有活动皮肤的所有附件。 collectedSkin = collectedSkin ?? new Skin("Collected skin"); collectedSkin.Clear(); collectedSkin.AddAttachments(skeletonAnimation.Skeleton.Data.DefaultSkin); collectedSkin.AddAttachments(equipsSkin); // 2. 创造一个重新包装的皮肤。 // 注意:GetRepackedSkin()返回的材质和纹理行为类似于'new Texture2D()',需要销毁 if (runtimeMaterial) Destroy(runtimeMaterial); if (runtimeAtlas) Destroy(runtimeAtlas); var repackedSkin = collectedSkin.GetRepackedSkin("Repacked skin",sourceMaterial, out runtimeMaterial,out runtimeAtlas); collectedSkin.Clear(); // 3.使用重新包装的皮肤。 skeletonAnimation.Skeleton.Skin = repackedSkin; RefreshSkeletonAttachments(); } catch (Exception e) { Debug.LogError($"OptimizeSkin 异常:{e.Message}"); } } }
5.测试代码:
using System.Collections; using System.Collections.Generic; using UnityEngine; using System; public class Test : MonoBehaviour { public SpineSkinDate[] array;//换局部皮的Sprite private SpineChangeSkin spineChangeSkin; private int index = 0; private void Start() { spineChangeSkin = GetComponent<SpineChangeSkin>(); } private void Update() { if (Input.GetKeyDown(KeyCode.A)) { if (array == null || array.Length < 1) return; if (index >= array.Length) index = 0; var skinData = array[index]; index++; spineChangeSkin?.ChangeShin(skinData.slotName, skinData.attachmentName, skinData.sprite); } } } [Serializable] public struct SpineSkinDate { public string slotName; public string attachmentName; public Sprite sprite; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。