[Unity]一段代码了解Spine局部换装 skeleton.SetSkin(newSkin); // 1. Set the active skin skeleton.

直奔主题:

但愿进来的朋友们可以帮助到你们。老规矩,话不多说,直接上代码:

方法1:

也是我后来用的方法,可能不一定是最好的,最适合你的,发出来供大家学习参考。


这也是很重要的一步,需要提前和美术同学制定好命名规则,换装的时候需要按照这个命名去给指定部位换装:

    //和美术约定好的Slot(插槽)名字
    const string face_slot_name = "s_face";
    const string hair_slot_name = "s_hair";

此处只定义了两个Slot(插槽),也就是当前Spine只支持这两个部位的动态换装:

    //定义目标Slot(插槽),并赋值。
    Slot face_slot;
    Slot hair_slot;

获取目标Slot:

    //初始化Slot相关
    private void init_slot_info()
    {
        //通过slot name获取指定的slot
        //当然前提得保证美术在制作Spine的时候预留了这些Slot
        face_slot = this.GetComponent<SkeletonGraphic>().Skeleton.FindSlot(face_slot_name);
        hair_slot = this.GetComponent<SkeletonGraphic>().Skeleton.FindSlot(hair_slot_name);
    }

定义一个集合来储存所有可换装的Attachment(附件):

    //所有皮肤下的所有附件
    //string 皮肤名
    //string 插槽名
    //List<Attachment>> 对应皮肤下对应插槽的Attachment
    Dictionary<string ,Dictionary<string , Attachment>> att_dic;

最后大概写一下换装流程: 

    /// <summary>
    /// 局部换装
    /// </summary>
    /// <param name="skin_name">目标皮肤名</param>
    /// <param name="part_name">目标部位名</param>
    public void change_part(string skin_name ,string part_name)
    {
        var tar_att = att_dic[skin_name][part_name];
        var tar_slot = get_slot(part_name);
        tar_slot.Attachment = tar_att;
    }

    /// <summary>
    /// 只写了大概,没写容错等其他内容
    /// </summary>
    /// <param name="slot_name">目标部位名</param>
    /// <returns></returns>
    private Slot get_slot(string slot_name)
    {
        switch (slot_name)
        {
            case face_slot_name:
                return face_slot;
            case hair_slot_name:
                return hair_slot;
            default:
                return null;
        }
    }

    //初始化Slot相关
    private void init_slot_info()
    {
        //通过slot name获取指定的slot
        //当然前提得保证美术在制作Spine的时候预留了这些Slot
        face_slot = this.GetComponent<SkeletonGraphic>().Skeleton.FindSlot(face_slot_name);
        hair_slot = this.GetComponent<SkeletonGraphic>().Skeleton.FindSlot(hair_slot_name);
    }

这个方法最后实际用的时候是可行的,就是拿到目标Slot,给他目标Attachment。但是参考网上的其他实现方式的话,这样好像显得有些粗暴,下面是第二种,也是我在网上看到的别人的实现方式。


方法2:

大概原理是,new一个空的皮肤,然后拿到目标Attachment。然后遍历当前Spine的所有Slot,如果当前Slot是目标Slot,则把目标Attachment赋值给Slot(Skin.SkinEntry entry = new Skin.SkinEntry(slot_index, slot_name, temp_att)),如果不是目标Slot,则获取当前Slot上的Attachment。最后把当前new出来的皮肤赋值给Spine。


代码:

    /// <summary>
    /// 局部换装
    /// </summary>
    /// <param name="skin_name">目标皮肤名</param>
    /// <param name="part_name">目标部位名</param>
    public void change_part(string skin_name, string part_name)
    {
        //先拿到目标Attachment
        var tar_att = att_dic[skin_name][part_name];
        Skin new_skin = new Skin("new_skin");
        var skeleton = this.GetComponent<SkeletonGraphic>().Skeleton;
        var slots = skeleton.Slots;
        foreach (var slot in slots)
        {
            string slot_name = slot.Data.Name;
            int slot_index = slot.Data.Index;
            Attachment temp_att = null;
            if (slot_name.Equals(part_name))
            {
                temp_att = tar_att; 
            }
            else
            {
                temp_att = slot.Attachment;
            }
            Skin.SkinEntry entry = new Skin.SkinEntry(slot_index, slot_name, temp_att);
            new_skin.Attachments.Add(entry, temp_att);
        }
        skeleton.SetSkin(new_skin);
    }

写在最后:

有一点一定要注意,就是在写代码之前,要和美术同学提前沟通并制定好命名规则,然后按这个命名去换装。别的暂时想不到了,欢迎提出问题一起学习。


20220519更新

需要在替换过attachment之后,执行下面两个方法:

        //skeleton.SetSkin(newSkin); // 1. Set the active skin
        skeleton.SetSlotsToSetupPose(); // 2. Use setup pose to set base attachments.
        animationState.Apply(skeleton); // 3. Use AnimationState to set attachments active in the current movement.

猜你喜欢

转载自blog.csdn.net/qq302756113/article/details/122302379
今日推荐