• Unity
  • Is there a way to get the active skins from a skeleton?

Related Discussions
...

I'm following the mix and match tutorial and have code like this:

SkeletonAnimation skeletonAnimation = GetComponent<SkeletonAnimation>();
Skeleton skeleton = skeletonAnimation.skeleton;
SkeletonData skeletonData = skeleton.Data;

// Create a new skin, and append those skins to it.
Skin myEquipsSkin = new Skin("my new skin");
myEquipsSkin.AddAttachments(skeletonData.FindSkin("human"));
myEquipsSkin.AddAttachments(skeletonData.FindSkin("black shirt"));

// Set and apply the Skin to the skeleton.
skeleton.SetSkin(myEquipsSkin);
skeleton.SetSlotsToSetupPose();
skeletonAnimation.Update(0);

Is there a way to get that the character is currently wearing the "human" and "black shirt" skins?

Here's what I'm trying to do: I want the character to wear multiple items at once, and I have a wardrobe screen where you can pick and choose what the character is wearing. One item (ie: a skin) can span multiple slots. e.g., a shirt could be on the chest slot and the left/right arm slots. I need to know which items/skins are currently being worn, so that I can appropriately enable and disable buttons in the wardrobe screen. Once you are wearing a pair of earrings, you shouldn't be able to equip them a second time. But, I don't know how to find out if you're wearing a pair of earrings. How do you find that out?

I don't suggest keeping application state in the skeleton. It is much better to keep your application specific state separate and use the skeleton only for rendering. For example, create a class for your character and track what items they have equipped, their name, level, etc then use that data to outfit a skeleton for rendering.

Thanks Nate. That's generally good advice, but check my reply here: How do I represent a lack of attachments in a skin?

The downside to doing this is a lot of the state/logic will be duplicated between spine and my code. I'll accept that that is the only way (if it is), but I see it as an opportunity for my Unity and Spine logic to get out of sync.

You should not need to ask the skeleton what skins are selected. You should know what skins are selected, you assembled them into a single skin after all. Any time they select a new skin, clear the skin, add all the skins they have selected. There is no chance for that to be out of sync. It may be that your game state is simple enough that you want to just throw skins at the skeleton and be done, but for anything more complex, such as saving the items the user has selected, you don't want to use the skeleton to store that state.

Nate wrote

You should not need to ask the skeleton what skins are selected. You should know what skins are selected, you assembled them into a single skin after all. Any time they select a new skin, clear the skin, add all the skins they have selected. There is no chance for that to be out of sync. It may be that your game state is simple enough that you want to just throw skins at the skeleton and be done, but for anything more complex, such as saving the items the user has selected, you don't want to use the skeleton to store that state.

Let's use this example:

You can equip Red Mohawk or Red Faux Hawk, but not both. You can equip Spiky Choker or No Necklace, but not both. When you equip one, it deselects the other in its slot. E.g., if you were wearing Red Mohawk and you wear Red Faux Hawk, you effectively unequipped Red Mohawk.

In Spine, I had to create slots to represent these concepts. But now, it feels like I have to do that all over again in my Unity code: As Harald said:

The setup would then be something like this:
base-skin= "caucasian character in underwear", "african character in underwear", ...
item-skin-earrings="normal earrings", "no earrings", "fancy diamond earrings"

Spine already knows exactly this information: e.g., That you can't wear "normal earrings" and "no earrings" at the same time because they share the same slots.

Now because I have to populate this "item-skin-earrings" list by hand (I think?), there's a good chance the Spine data and the Unity data will get out of sync. e.g., I could add a new kind of earring in spine and forget to add it to the list in unity. I could make a typo in one place and call it "no earings" instead of "no earrings," etc. If that happens, the item may not show up in this graphic, or the wardrobe may not know to unequip "no earrings" when you click "new earrings."

Anyway, this isn't a huge deal. I just gotta be sure to keep everything in sync. But IMO, if I could just ask the skeleton "Which skins are you wearing?" this would remove a set of potential mistakes I could make.

I may be thinking about this incorrectly! I'm very new to Spine. Let me know and thanks for your patience!


Any time they select a new skin, clear the skin, add all the skins they have selected. There is no chance for that to be out of sync.

I guess my main confusion is over this part. How do I know that when they select a new skin, that means they deselected another skin? e.g., Wearing "diamond earrings" means to deselect all other kinds of earrings? Is there any way to do that other than to write that information by hand in Unity code?

It's not uncommon for the application to know what is in the skeleton, such as what animations it has so it can play them at the right time. Often the app needs to show lists of items that can be equipped and for each item it needs to know the price, damage, etc. You wouldn't want to store that in Spine.

For your use case I expect you want to show items by category: hair, eyes, head shape, hat, etc. Only one of each category can be selected at a time (or else you have to code the rules in Unity) and so you'd want to show them to the user separated by category, so the user knows equipping this thing replaces that thing, rather than a single, long list.

If you really must, you can look at the composite skin and see what slots it has attachments for, then try to determine from that which skins were selected.

Cool, cool. From your reply, I'm inferring that I understand the Spine API correctly.

I thought of something clever, and that always makes me think it's a bad idea. I wanted to get your thoughts:

In Spine, I could name the skin with a code, like "Diamond Earrings [earrings]", "No Earrings [earrings]" In unity, I could look at all the skins a skeleton has. The name before the brackets would go on the picture I've shown you above, but between the brackets could represent a slot. Then, it's simply a matter of parsing this information in unity code. I could place it all into a Dictionary<string, List<Skin>> where the key is the the string between the brackets and the value is a list of skins. E.g., in this example, dictionary["earrings"] would return a list of the "Diamond Earrings" and "No Earrings" skins.

If this is a really bad idea, let me know. To me it feels like a good compromise about keeping all the data in one place.

I think it's OK to have conventions like that. You are restricted by how much data you can jam into the name in Spine, so the mess is limited. If we allowed name/value pairs to be defined in Spine it would be much more powerful, allowing you to really mess things up! I know people will start using Spine as a game data config tool, storing damage values, etc in their skeletons.
Name/value annotations · #25 · EsotericSoftware/spine-editor

I'm down with that feature. In the end, I decided to not use my naming convention, because I realized that I need to add descriptions to my items and maybe icons, so no matter what, my data has to be in both spine and unity. A programming language (c#) can do a slightly better job of enforcing the unity slot system than spine could in this case.