Edit: Solved in Update 2, but if you could review my code, that would be great!
...or that's what I think it's happening because I go from this...:
...to this...:
I have logic to randomize her appearance and clothes, hair included. I use a combined skin that works perfectly well when the character is instantiated, as you can see in the first image.
But when I trigger the same logic to randomize her again, this is what happens.
I use PlayMaker with a modified action I managed to make for my needs. It accepts multiple skin names to add in sequence, and it also has an option to add them to the current one, but that's disabled in this case, so it starts fresh.
The meaty part is like this...
Edit: the full code is at the end of the post.
Anyway, I suspect that many skin bones and constraints are not being applied, because that huge stretching on the shirt also happens in Spine if the correct constraints are not enabled (there's a path constraint for the breasts parts). The hair also has skin bones, because I have 20 hairstyles, so I hide the non-relevant bones.
It's a real mess, and after having done a lot of troubleshooting I don't know how to continue. Could you maybe point me in the right direction? Is this something you've already seen before?
Of course, I'm open to giving as much feedback possible, because this is a huge show-stopper for me. If I can't switch the appearance of the characters, just imagine... :rolleyes:
Thank you.
UPDATE:
Well, after a lot of troubleshooting I suspect that what it makes the constraints not being enabled is because most of them were added by the editor itself (notifying of that fact).
I've encountered that problem in other instances, that if you react like "Ah... okay, that's nice, thank you Spine!" and keep working, the actual outcome is that even if the constraints are listed as members of the OTHER skins, the truth is that those skins behave like if they don't have them at all. Therefore, the constraint doesn't activate fully.
So, I think this is actually an editor issue.
That problem with the breasts on the pics, it also happened with the skirts. I've just needed to delete all skin bones they had and re-assign them again. But this time, when Spine "helpfully" said...:
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_ExtraLong_Blue, skeleton: Female_Side]
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_ExtraLong_Green, skeleton: Female_Side]
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_ExtraLong_Red, skeleton: Female_Side]
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_Long_Red, skeleton: Female_Side]
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_Long_Blue, skeleton: Female_Side]
WARNING: Bone [bone: Skirt_Short_Back, skeleton: Female_Side] added to additional skin: [skin: Female/Clothes/Skirt/Skirt_Long_Green, skeleton: Female_Side]
...I said "Thanks, but no thanks...", and pressed Ctrl+Z" to revert those skins to their original state. And then I selected those myself and added the appropriate bones with the "Add to Skin" button.
And I'm afraid that's also the reason why the hair (I have 20 styles * 31 colors) and the breasts are also behaving like that. So yeah, I'll try now with that and update again.
But if this is an editor bug that I've uncovered, it's pretty BIG, lol. :p
UPDATE 2:
Okay, found the problem... it only took me 24 hours of despair and zealous obsessive trial and error.
Regardless of what I've said about the editor, which yes sometimes it happens to me, it turned out that I need to run that PlayMaker action TWO times, one after another.
Why that happens, I haven't the slightest idea, LOL.
But that only solved the issue of skin constraints and bones not being correctly applied. However, I still had this problem...:
That's like if it wasn't clearing the previous skin first and adds more skins instead, overwriting slots.
That would explain the hair attachments from other more complex hair skins (with more slots). Also, that long sleeve on the forearm and the knot on the front, when they actually shouldn't be there now that the t-shirt is activated instead.
And funnily enough, as I was writing this second update, I thought of manually clearing the supposedly already null skin variable that my PlayMaker action uses... and that fixed it.
I also don't understand this, because I have a line turning that variable into null every time the action is run... but at this point, I give up in trying to see any sense from this.
However, I'd appreciate it a lot if you could take a look at my script. Maybe you could explain why I need to run it two times and also clear that variable? :hmm:
Here's the full thing...:
using UnityEngine;
using Spine;
using Spine.Unity;
namespace HutongGames.PlayMaker.Actions
{
[ActionCategory("Spine")]
[Tooltip("Sets/Adds/Combines a given number of skins.")]
public class SpineSkinAction : FsmStateAction
{
[RequiredField]
[CheckForComponent(typeof(SkeletonAnimation))]
[Tooltip("The GameObject with an SkeletonAnimation component.")]
public FsmOwnerDefault gameObject;
[RequiredField]
[Tooltip("Array of Skins to combine.")]
public FsmString[] skins;
[Tooltip("")]
public FsmFloat delay;
[Tooltip("Adds the skin/s to the current one.")]
public FsmBool add;
Skin combinedSkin = new Skin("my new skin");
GameObject go;
SkeletonAnimation skeletonAnimation;
bool called;
float ellapsedDelay;
public override void Reset()
{
skins = new FsmString[1];
delay = 0;
called = false;
ellapsedDelay = 0;
combinedSkin = null;
add = false;
}
public override void OnEnter()
{
called = false;
go = Fsm.GetOwnerDefaultTarget(gameObject);
if (go == null)
{
Finish();
}
else
{
if (delay.IsNone)
{
Do();
}
else
{
ellapsedDelay = delay.Value;
}
}
}
public override void OnUpdate()
{
if (!delay.IsNone && !called)
{
ellapsedDelay -= Time.deltaTime;
if (ellapsedDelay <= 0)
{
Do();
}
}
}
void Do()
{
called = true;
skeletonAnimation = go.GetComponent<SkeletonAnimation>();
Skeleton skeleton = skeletonAnimation.skeleton;
SkeletonData skeletonData = skeleton.Data;
if (skeletonAnimation)
{
// Clear combined skin (which was supposedly null already, LOL...)
combinedSkin.Clear();
// Add existing skin to the new one, if adding.
if (add.Value)
{
combinedSkin.AddSkin(skeleton.Skin);
}
// Check if skins exist, before trying to add them to the combined skin.
foreach (FsmString skinPath in skins)
{
if (skeleton.Data.FindSkin(skinPath.Value) == null)
{
// Skin not found in SkeletonData
Debug.LogWarning("Skin " + skinPath.Value + " does not exist. Skipped.");
}
else
{
// Add skin
combinedSkin.AddSkin(skeletonData.FindSkin(skinPath.Value));
}
}
// Set and apply the Skin to the skeleton.
skeleton.SetSkin(combinedSkin);
// Reset to Setup pose
skeleton.SetSlotsToSetupPose();
// Update skeleton
skeletonAnimation.Update(0);
}
else
{
Debug.LogError("No SkeletonAnimation component found!");
}
Finish();
}
}
}
Thank you.