• Unity
  • SkeletonGraphic: Changing attachement?

  • Düzenlendi
Related Discussions
...

Hi,

I'm using SkeletonGraphic with a UI mask to do this:

Bad news is: I need to change attachements of this SkeletonGraphics depending on player equipment.
I've been reading the forum about that topic but I'm not sure about the definitive answer... Is there absolutely no way of changing the Attachments of a SkeletonGraphic? It doesn't need to be real time, it would just happen once in a while upon scene start.

Note: I've tried the RepackOnStart example Pharan provided but not sure how it would work for me since I don't use the Spine skin system. I use my own skin system to handle SetAttachement.

If that's not possible at all, would you have an idea about how to obtain the above result with a classic Spine animation MeshRenderer? Basically, how to mask a MeshRenderer? I know it's related to Unity but it seems overly complicated :S

Thanks

Letting UI and world renderer masking mix is kind of weird.

There are two things that I think can work.

  1. Repacking.
    The point is not that you need to use the skin system, but that you need to be able to repack attachments into a new single texture and then to use those new attachments that reference that new texture. So if you can collect all those attachments you need, we might be able to repack them? And then you have to make sure you use the repacked ones.

  2. Have a special shader that does stencil stuff. I'm not sure how the UI Masking behavior is defined but it does rely on the stencil buffer. If you had a shader that had the correct stencil properties defined, it would interact with the UI masking system. But I think only within the canvas's context.

Unity 2017.1 actually added SpriteMask and we use the stenciled shader method. ([unity] Unity 2017 SpriteMask support · #941)
It does require that your material uses the shader.
Similar to the UI case, the compare reference value is kind of a guessing game at this point.

Personally, I think we should go after Repacking.

Letting UI and world renderer masking mix is kind of weird.

Not sure what you meant!

  1. Repacking
    If I understand correctly: from the huge player atlas containing all possible equipment and skin, we would have to locate the parts needed, pack them into a texture and repack the SkeletonGraphic with those?
    I'm digging once more into your RepackOnStart example. Basically, I should replicate the behavior of GetRepackedSkin for my own system, right?
    In addition, what about all the weird exceptions? I have tons of small constraints like, hide this beard if wear this helmet, color the hair with a certain teint, etc. which is mostly handled using Attachment colors. Won't this be a problem as well?
    This is getting so hardcore for a god damn avatar in HUD 😃

  2. I have zero knowledge in shader and I feel you think that method is more dirty so I'll start to dig the first one as you suggest.


  1. Oh and what about clipping mask? Don't you think I could cheat a little bit with this? Like, trying to make a fitting mask in spine, then playing that masked animation on top of the UI. If the position match perfectly that could do as a mask? (I've not tried clipping mask yet so I'll check how they work)

Oh, I think I misread your first post.
"Is there absolutely no way of changing the Attachments of a SkeletonGraphic?"
You change attachments normally, like you would in SkeletonAnimation.

SkeletonGraphic's limitation is only that it needs to use one texture. Because its base class that's being used to integrate into Unity's UI, MaskableGraphic, also needs to use one texture. That's why repacking is the solution.

Spine's Clipping feature doesn't really help or hurt you if you use it instead of Unity's own masking. You would still need to solve the problem of needing one texture. Unity's masking is probably more performant though because it's stencil-based, so never mind using Clipping.

There's no need for you to try to mimic the GetRepackedSkin method. I've already written the alternate version of it. It will be out with the next unitypackage update soon.
On your end, you need code that has these 3 steps.

void Start () {
   var skeletonGraphic = GetComponent<SkeletonGraphic>();
   var skeleton = skeletonGraphic.Skeleton;
   var skeletonSlotList = skeleton.Slots;

   // 1. Collect original attachments
   var originalAttachments = new List<Attachment>();
   for (int i = 0, n = skeletonSlotList.Count; i < n; i++) {
      originalAttachments.Add(skeletonSlotList.Items[i].Attachment);
   }

   // 2. Use the GetRepackedAttachments Utility method.
   var outputAttachments = new List<Attachment>();
   AtlasUtilities.GetRepackedAttachments(originalAttachments, outputAttachments, materialPropertySource, out outputMaterial, out outputTexture);

   // 3. Use the newly repacked attachments to your slots, instead of the original attachments.
   for (int i = 0, n = skeletonSlotList.Count; i < n; i++) {
      skeletonSlotList.Items[i].Attachment = outputAttachments[i];
   }

   // Make sure your SkeletonGraphic now uses the new texture.
   skeletonGraphic.OverrideTexture = outputTexture;
}

Because you have your own "custom" skin system, step 1 and step 3 will probably be more complicated than that code. But the point stays the same. You need a way to collect your original attachments into a List<Attachment>, and then integrate the new output collection attachments in List<Attachment> into your skeleton again.

edit: The unitypackage is now up. Dated today. http://esotericsoftware.com/spine-unity-download

You change attachments normally, like you would in SkeletonAnimation.

Wait...what?

I get it. It works now ^^ I got over worried by reading all the issues about swapping attachment, but I've none since I use one texture only, so no need to repack etc. I just made sure that my custom system could handle SkeletonGraphic as well, and it works perfectly.

Thanks for your help, always on point 🙂