当前位置:   article > 正文

Unity Spine 局部换皮_unity spriteskin

unity spriteskin

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}");
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/122618
推荐阅读
相关标签
  

闽ICP备14008679号