• Unity
  • Question about proper way to handle mix and match

Related Discussions
...

Sorry for the second forum question in a day.

I just watched the new features video for Spine and I'm loving everything I've seen. I do have a question about the mix and match stuff.

The Unity project I'm working on requires allowing players to customize my characters heights and body proportions. (So swapping out chest/arms/legs/face/hair ect...)

I also need to support a large range of outfit pieces that I'd swap in too.

In the past I experimented with building all my skins at runtime dynamically by using sprites and in futre hopefully copying the deformation data for the sprites too (especially for cloth on clothes)

I guess my question is, with such a large range of need combustibility, is it still possible (and a good practice) to generate all my needed skins at runtime for body types/ outfits from sprites, and it is possible to dynamically change the skeleton at runtime.

And do you have suggestions as to how I should go about things to maybe improve my workflow.

Anisoft wrote

I guess my question is, with such a large range of need combustibility, is it still possible (and a good practice) to generate all my needed skins at runtime for body types/ outfits from sprites

It depends. In general, it should not be a problem either way (single sprites vs parts Spine atlas textures), as long as you repack the resulting skin at runtime in the end, to preferrably a single atlas texture.

Anisoft wrote

and it is possible to dynamically change the skeleton at runtime.

Yes, you can change the skeleton at runtime.
You can assign a different skeletonDataAsset at runtime as follows (example is for SkeletonGraphic, but the same applies to SkeletonAnimation):

skeletonGraphic.skeletonDataAsset = skeleton;
// make sure that initialSkinName and startingAnimation are cleared/set to values that exist in the new skeleton
skeletonGraphic.initialSkinName = "goblin";
skeletonGraphic.startingAnimation = "";
skeletonGraphic.Initialize(true);

You can also instantiate skeletons at runtime.

The packing had me interested since...if I do it via sprite in unity...generating a single texture would only apply per single spine sprite. If you had many different characters it'd likely get costly. I forget if there is a way to generate an atlas in unity that can be shared across sprites

I assume the spine parts atlas makes it easy to do that since it just packs textures for everything I use...

However the unity one...I don't remember if it can pack a shared atlas or not

When you say instatiate does that include stuff like changing different bone heights or lengths?

If I wanted to add a height slider for example

Anisoft wrote

When you say instatiate does that include stuff like changing different bone heights or lengths?

Instantiating a skeleton via code at runtime will have a similar result like when you drag-and-drop the skeleton asset into a scene. Single bone position or scale values will not be different.

Perhaps as a simple solution you could create an additive animation that applies larger scale to some bones and then apply this animation on a separate track, with 0-100% alpha to apply a configurable amount.

That additive animation solution seems like a really good idea for how to handle scaling the character, Ill give it a try thank you so much!.

I'm still unsure how I should go about optimization for the textures. my idea was use spine to create only a template file, then replace all the sprites within unity. I guess with that technique I can just pack all the sprites per character into the desired material.

I do worry about performance for multiple spine sprites. I'm curious tho, couldn't I just pack all my sprites into a single atlas in unity, and then apply each of those attachments in replacement of the template, and it'd just use the 1 shared sprite material?

(The shared material for all the sprites?) (for example using texture packer to pack all my sprite pieces together and importing into unity)

This is also important for normalmaps, as I'd like to make each normal map seperately and then pack them together as same layout with something like Texture Packer.

Tho maybe in the end it is just better to pack per sprite material, since it does seem to allow the most freedom in how I pack my sprite content. I don't plane to have more then like 20 spine characters per scene... so thats like... 20 drawcalls unless a specific sprite like a sword needs a fire material...

I guess Ill have to test more stuff out!

If you can fit the images of multiple characters into a single atlas page, even better.

The way you pack these images to an atlas is basically up to you. You can use Spine's texture packer (accessible from the main Spine menu) to pack them grouped by image folders. You could use compatible third party packing software like Texture Packer. You could as well pack them at runtime via code, if it's uncertain which images will be used and space is scarce. We have recently extended runtime packing by functionality for packing normalmaps and other maps along with the main texture.

Harald wrote

You could as well pack them at runtime via code, if it's uncertain which images will be used and space is scarce. We have recently extended runtime packing by functionality for packing normalmaps and other maps along with the main texture.

Oh thank you!

Is there a guide for packing the normalmap sprites with the main sprites for this?


Also from the mixandmatch demo (and testing it out a few months ago) I can see how easy it is to pack an atlas for an individual sprite. However its only for 1 character, is it possible to pack an atlas for multiple? I didn't test it out and see.

(Sorry for all the questions, you are all amazingly helpful, thank you so much.)

Anisoft wrote

Is there a guide for packing the normalmap sprites with the main sprites for this?

There is a forum posting here with a code example on how to pack normalmaps along with the main maps:
Mix and Match with Skins

Anisoft wrote

However its only for 1 character, is it possible to pack an atlas for multiple?

Yes, as the GetRepackedSkin() method takes a skin as input, you could first combine multiple skins first and then repack it:

Skin combinedSkin = new Skin("CombinedSkin");
combinedSkin.AddSkin(skeletonAnimation1.Skeleton.Skin);
combinedSkin.AddSkin(skeletonAnimation2.Skeleton.Skin);
// then repack as before

Thank you so much, that's very useful!

So I guess I'm going to just to have to assign each part of the sprite into each slot for all characters, then dynamically pack them all

I assume I can extend this to pack stuff into specific channels too (for specular/metallic)

Another thing, I remember a while back I was experimenting with this I was trying to allow me to see changes in the editor. However apparently stuff in the native spine or spine unity runtime had code that wouldn't forcefully refresh my changes.

Has that been changed yet or is that still an issue.

Lastly I have some wip of the stuff I've been testing out with normals and spine and custom lighting. However it features nudity (nsfw) so I won't post it here. If you'd like to check it out I can email you all what I've been doing and possibly it help you all see what I'm trying to pull off here! 🙂.

Anisoft wrote

So I guess I'm going to just to have to assign each part of the sprite into each slot for all characters, then dynamically pack them all

Yes, as shown in the Spine Examples/Other Examples/Mix and Match scene.

Anisoft wrote

I assume I can extend this to pack stuff into specific channels too (for specular/metallic)

You can use the existing API for any material parameter other than normal maps, just adjust the line of the linked example code above accordingly:

int[] additionalTexturePropertyIDsToCopy = new int[] { Shader.PropertyToID("_BumpMap") };

to e.g.

int[] additionalTexturePropertyIDsToCopy = new int[] { Shader.PropertyToID("_BumpMap"), Shader.PropertyToID("_MetallicGlossMap") }; 

Just look at the material parameters with Debug view active in the inspector to see the property names.

Anisoft wrote

Another thing, I remember a while back I was experimenting with this I was trying to allow me to see changes in the editor. However apparently stuff in the native spine or spine unity runtime had code that wouldn't forcefully refresh my changes.

Editor preview of any custom skin re-combination (while not in play mode) would require you to write the respective editor code. Or did you mean something else?

Anisoft wrote

If you'd like to check it out I can email you all what I've been doing and possibly it help you all see what I'm trying to pull off here! 🙂.

Thanks for offering. At the moment I think I understand pretty well what you need, but we'll resort to it as soon as we end up at a dead end 🙂.

Thanks for the detailed response!

Editor preview of any custom skin re-combination (while not in play mode) would require you to write the respective editor code. Or did you mean something else?

Yea I remember writing something like an onValidate or something similar. Some sort of editor script that'd allow me to refresh in the editor. I remember one of the spine editors previously would overwrite the skin back to its default skin.

I was curious if that had been adjusted so its possible to do what I did before or if there is another workaround to allowing my editor window to show the skins.

With the way I handle creating sprites albedo/normals/spec/gloss I'm thinking it may be best to just keep a bunch of sprites separated within the project with a relevant material and merging them at runtime.
I plan to have hundreds of source sprites (which may make the file size a bit larger then if I were to pre-pack them) however if I'm correct, other then file size, dynamically packing them all run time wont effect performance beyond the actual packing process when instantiating my characters?

What's difficult to think about is that, if I have tons of sprites used for all kinds of equipment to builds all kinds of different characters. To some extent it be very convenient to just have all sprites packed into 1 texture (or rather few textures). However the method you showed to dynamically pack skins appears as If I have to have pre-defined skins with sprites assigned that I merge into one.

So packing lets say 20 different hair sprites into a single texture along side the rest of her body. Or 20 different arm sprites, doesn't really seem possible that way. (I guess im naively thinking I can pre pack all my sprites at the start of the game)

However maybe I'm just overthinking stuff, maybe its okay to leave all the source sprites in the project and just generate the specific textures I need only when I need them. Do you just suggest I do that?

Sorry so much for the long winded questions... I've been studying a good workflow for weeks and have been trying to wrap my head around this. Thanks so much for your help.

Anisoft wrote

Yea I remember writing something like an onValidate or something similar. Some sort of editor script that'd allow me to refresh in the editor. I remember one of the spine editors previously would overwrite the skin back to its default skin.

This has now been improved, you can now set the property skeletonRenderer.EditorSkipSkinSync to disable any skin overrides from the SkeletonAnimation Inspector. A new unitypackage has just been uploaded, you can download it here as usual:
Spine Unity Download

For reference, it was this issue:
https://github.com/EsotericSoftware/spine-runtimes/issues/1469

Regarding the other questions:
You could go either way, whatever suits your workflow and assets more. Either pack them ahead of time and then access single parts or have them separate from the start. It should not matter too much if you end up repacking them differently later.

Harald as usual you and everyone else here are truly incredible! Thank you so much for your incredible quick and fast support as always. Without you I'd never have made it as far as I have so really, thank you so much! Have an amazing day and thanksgiving week!

Thanks very much for your kind words, very much appreciated! :nerd: We're always striving to make the API as flexible and comfortable to use as we can, and concise feedback always helps us a lot in removing any obstacles we have not yet thought of!