• RuntimesUnity
  • How to change skin by RegionAttachment?

I change skin like this way:
https://zh.esotericsoftware.com/forum/d/26713-skin-repack-can-not-work

I have many different png pictures. I use the following method to change the skins. Each picture acts as a sprite:

public void ChangeAvatar(Sprite sprAvatar, string strTargetSlot,string strTargetAttach)
{
Debug.Log("sprAvatar:" + sprAvatar.name);
var templateSkin = skeleton.Data.FindSkin("default");
int slotIndex = skeleton.Data.FindSlot(strTargetSlot).Index;
Attachment templateAttach = templateSkin.GetAttachment(slotIndex, strTargetAttach); // STEP 1.1
Attachment newAttach = templateAttach.GetRemappedClone(sprAvatar, sourceMaterial, pivotShiftsMeshUVCoords: false); // STEP 1.2 - 1.3
if (newAttach != null) customSkin.SetAttachment(slotIndex, strTargetAttach, newAttach); // STEP 1.4
this.skeleton.SetAttachment(strTargetSlot, strTargetAttach);//设置显示新的服装
}

Therefore, each time this method is called, a separate material will be generated:

So I conceived a solution:

  1. Read these images as 2D textures, merge them into a larger texture named "biggerTexture", and store the corresponding UV (position) information.

  2. Assign the UV information of each component in the biggerTexture to a RegionAttachment, and then assign each RegionAttachment to the Spine object. The Spine object will use this biggerTexture as the material texture and display correctly.

    Unfortunately, I was unable to complete this process as planned. I only merge the different images into the biggerTexture.
    When I create a RegionAttachment, and assign it to the Spine object. There was a problem at this step, resulting in a messed up display of the graphics on my Spine object.

Is my idea feasible? Can you provide the implementation code?

Related Discussions
...

Your idea of merging multiple images into a larger texture and then using UV mapping to display them correctly in Spine is indeed feasible. Below is a step-by-step guide and implementation code to help you achieve this.

Step-by-Step Guide

  1. Merge Images into a Larger Texture: Combine your individual images into a single larger texture (biggerTexture).
  2. Calculate UV Coordinates: Determine the UV coordinates for each image within the larger texture.
  3. Create RegionAttachment: Create a RegionAttachment for each image and set its region to the corresponding part of the larger texture.
  4. Assign RegionAttachment to Spine: Assign the RegionAttachment to the appropriate slot in your Spine skeleton.

Implementation Code

Here is a sample implementation in C# for Unity:

using UnityEngine;
using Spine;
using Spine.Unity;

public class SpineSkinChanger : MonoBehaviour
{
    public SkeletonAnimation skeletonAnimation;
    public Material sourceMaterial;
    private Skin customSkin;

    void Start()
    {
        customSkin = new Skin("customSkin");
        skeletonAnimation.Skeleton.SetSkin(customSkin);
        skeletonAnimation.Skeleton.SetSlotsToSetupPose();
    }

    public void ChangeAvatar(Texture2D biggerTexture, Rect[] uvRects, string strTargetSlot, string strTargetAttach)
    {
        int slotIndex = skeletonAnimation.Skeleton.Data.FindSlot(strTargetSlot).Index;
        Attachment templateAttach = skeletonAnimation.Skeleton.Data.FindSkin("default").GetAttachment(slotIndex, strTargetAttach);

        if (templateAttach is RegionAttachment regionAttachment)
        {
            for (int i = 0; i < uvRects.Length; i++)
            {
                Rect uvRect = uvRects[i];
                RegionAttachment newAttachment = regionAttachment.GetRemappedClone(biggerTexture, sourceMaterial, uvRect);
                customSkin.SetAttachment(slotIndex, strTargetAttach, newAttachment);
            }
        }

        skeletonAnimation.Skeleton.SetAttachment(strTargetSlot, strTargetAttach);
    }
}

public static class RegionAttachmentExtensions
{
    public static RegionAttachment GetRemappedClone(this RegionAttachment original, Texture2D texture, Material material, Rect uvRect)
    {
        RegionAttachment newAttachment = new RegionAttachment(original.Name);
        AtlasRegion region = new AtlasRegion
        {
            page = new AtlasPage { rendererObject = material },
            u = uvRect.xMin,
            v = uvRect.yMin,
            u2 = uvRect.xMax,
            v2 = uvRect.yMax,
            width = (int)(uvRect.width * texture.width),
            height = (int)(uvRect.height * texture.height),
            originalWidth = (int)(uvRect.width * texture.width),
            originalHeight = (int)(uvRect.height * texture.height),
            offsetX = 0,
            offsetY = 0,
            rotate = false,
            name = texture.name
        };

        newAttachment.SetRegion(region);
        newAttachment.UpdateOffset();
        return newAttachment;
    }
}

Explanation

  1. ChangeAvatar Method:

    • Takes a Texture2D (biggerTexture), an array of Rect (uvRects), and the target slot and attachment names.
    • Finds the slot index and template attachment.
    • Iterates through the uvRects to create new RegionAttachment instances with the correct UV mapping.
    • Sets the new attachment to the custom skin and updates the skeleton.
  2. GetRemappedClone Extension Method:

    • Creates a new RegionAttachment and sets its region using the provided UV coordinates.
    • Updates the offset to ensure the attachment is displayed correctly.

Summary

This code merges multiple images into a larger texture and uses UV mapping to display them correctly in Spine. The ChangeAvatar method updates the skeleton with the new attachments, ensuring the graphics are displayed as intended.