Hey Nate, thanks for the detailed response, sorry I took a while to follow up here. Spine is just incredible, and the c# and Unity runtimes have been great to work with. I'm a week and a half into putting animations in my game and it already looks incredible (will post pics/vid soon).
Changing the atlas page materials would change the material for all SkeletonAnimations using that atlas, correct?
The solution I decided on was to create another atlas using a different material with the shader I want, and then switch characters over to that atlas during gameplay. Obviously this will mess with batching, but that's inherent in using different materials anyway. Are there any other drawbacks to this I'm not seeing?
All I'm doing is creating another skin based on the one the skeleton has, but creating the clone skin using a different AtlasAsset which uses a material with a different shader. Then, swapping shaders during gameplay just involves setting the appropriate skin.
I found the method for cloning a skin on the forums here and made a few modifications:
public static Skin CloneCurrentSkinWithNewAtlas(SkeletonAnimation skelAnim, string skinName, Atlas atlas)
{
Skeleton skeleton = skelAnim.skeleton;
if (skeleton.data.FindSkin(skinName) != null)
throw new Exception("A skin named " + skinName + " already exists in the SkeletonData.");
//set the skin we're cloning to the default skin if no skin is set on the skeleton.
Skin currSkin = skeleton.Skin ?? skeleton.data.FindSkin("default");
Skin newSkin = new Skin(skinName);
//create an attachment loader to use; allocation seems necessary here
AtlasAttachmentLoader atlasAttachmentLoader = new AtlasAttachmentLoader(atlas);
List<Slot> slots = skeleton.slots;
List<Attachment> slotAttachments = new List<Attachment>();
List<string> attachmentNames = new List<string>();
// for each slot in the skin, get the attachment names, image names, make copy of the attachement to the new skin
foreach(Slot slot in slots)
{
//get the slot index
int slotIndex = skeleton.FindSlotIndex(slot.data.name);
//get attachments from this slot
slotAttachments.Clear();
currSkin.FindAttachmentsForSlot(slotIndex,slotAttachments);
//get the names
attachmentNames.Clear();
currSkin.FindNamesForSlot(slotIndex,attachmentNames);
//for each attachment in this slot, copy it to new skin
for(int i=0;i<slotAttachments.Count;i++)
{
Attachment att = slotAttachments[i];
string attName = attachmentNames[i];
string spriteImageName = att.Name;
Attachment newAtt = atlasAttachmentLoader.NewAttachment(newSkin, AttachmentType.region, spriteImageName);
RegionAttachment newRegAtt = newAtt as RegionAttachment;
RegionAttachment oldRegAtt = att as RegionAttachment;
//copy properties from old regionattachmet to new one
newRegAtt.x = oldRegAtt.x;
newRegAtt.y = oldRegAtt.y;
newRegAtt.scaleX = oldRegAtt.scaleX;
newRegAtt.scaleY = oldRegAtt.scaleY;
newRegAtt.rotation = oldRegAtt.rotation;
newRegAtt.width = oldRegAtt.width;
newRegAtt.height = oldRegAtt.height;
newRegAtt.UpdateOffset();
newSkin.AddAttachment(slotIndex, attName, newRegAtt);
}
}
skeleton.data.AddSkin(newSkin); //adds the skin to the skeleton data
return newSkin;
}