- Uređeno
NULL attachment data when drawing slots
Hi,
This is either a libGDX runtime issue, or spine file export issue, but either way, there is some kind of inconsistency there.
We have an animation with multiple skins, when it is exported in final JSON file there is a list of skins, each of skins containing their attachment data, yet the first one in that list is a skin called "default", and that skin does not contain any attachments. t is also not shown in spine software, but it is in JSON.
Now when runtime loads that, the way it does it - it really matters which skin it reads first, so due to default skin having no attachments the following issue occurs. Even though it's rendering proper skin, when it goes into draw method, and iterates of Slots, the attachment field in each slot is "null" thus nothing gets rendered.
Previously we had a quick workaround - which was to create skin named default, and then remove it, which was removing default skin from JSON, and fixing the problem. Now, this can't be done because in new spine version default is "considered a reserved name" so can't be created, thus can't be removed. And so we are stuck with this skin in the son that makes animation not render in runtime.
Can you advise if this is a wrong export or JSON is correct and it's just the wrong runtime? or a bug?
Versions we are using:
Spine Software: 3.8.95
libGDX Spine Runtime: 3.9 (snapshot)
Hello, the default skin is not a bug, from the Runtime Skins - Spine Runtimes Guide page:
All attachments defined in the skeleton data are placed in a skin. Attachments that were not in a skin in the Spine editor will appear at runtime in a skin named default, where the name in the skin is the same as the attachment's name. When Skeleton getAttachment needs to find an attachment by name, it first looks in the skeleton's current skin. If the attachment is not found, then it looks in the SkeletonData's default skin.
See also:
Skin
SkeletonData defaultSkin
Hi! I see, but I am not sure I understand why would libGDX runtime fail due to that and render nothing on other skins. (Given I am using a new runtime). Should it be updated to specific version?
UPD: Found a fix, getSkins was always returning default skin, and when you set that skin it was breaking it forever, so trick is to never set to default skin. and ignore it. But I guess, isn't it correct to make runtime NOT report default in getSkins call? since it's something internal anyway?
It is helpful to separate the 1) problem (ie expected versus actual behavior) from 2) the cause and also from 3) any potential solutions. It's great to discuss those 3 things, but they should remain separate to keep things clear.
azakhary86 wrotedue to default skin having no attachments the following issue occurs. Even though it's rendering proper skin, when it goes into draw method, and iterates of Slots, the attachment field in each slot is "null" thus nothing gets rendered.
OK, your slots not having attachments is the issue.
Do you set a skin? After you set a skin do you call Skeleton setSlotsToSetupPose
? See Skeleton setSkin
, specifically the behavior about changing the attached attachments when setting a skin. The runtime doesn't know what attachments you want attached. It doesn't assume you want them all attached, and that wouldn't make sense for many skins
when there are multiple attachments for the same slots, it can't know which one you want. Skeleton setSlotsToSetupPose
is the easy way to get it to attach attachments from the skin, otherwise you'll need to explicitly attach the attachments you want.
You can use Skeleton Viewer to verify the data loads and renders as you expect:
Skeleton Viewer
It's like a version of the Preview view inside Spine, built with libgdx and spine-libgdx with the source available. When you click a skin in the list, Skeleton Viewer sets the skin and calls setSlotsToSetupPose
:
spine-runtimes/SkeletonViewer.java at 3.8
Erika explained the default skin. It is in your data because you have a bounding box named dialog-viewport
that is not in a skin, so it goes in the "default" skin. If you delete this so you have no attachments outside skins, then there is no default skin in the exported skeleton data. The default skin does not affect your issue at all though.
It seems I wasn't actually doing setSlotsToSetupPose ever.
What I was doing is just, getting first skin keleton.getData().getSkins().first(); and then setting it with setSkin. And since default is the first one, I was getting behaviour with null attachments in slots - even if i set skin to "blue" or any other afterward, nothing was changing.
Never setting default skin fixes the problem. And now I have also tried calling "skeleton.setSlotsToSetupPose();" every time after i set new skin, and even if I "break" it with default skin, later on calling skeleton.setSlotsToSetupPose(); was fixing it as well, so that's nice!
So I guess solution is to - never consider default in my list of skins for preview, and also just call the setSlotsToSetupPose every time I change skin, and in this case it all seems to be working.
Thank you so much!
azakhary86 wroteWhat I was doing is just, getting first skin keleton.getData().getSkins().first(); and then setting it with setSkin. And since default is the first one, I was getting behaviour with null attachments in slots - even if i set skin to "blue" or any other afterward, nothing was changing.
Ah, I see. This behavior is because setSkin
says: "If there was no old skin, each slot's setup mode attachment is attached from the new skin." When you didn't have a default skin, this was happening the first time you setSkin
. After that when you setSkin
it would do the other behavior described on Skeleton setSkin
, which was usually what you wanted.
Skipping the default skin from your list of skins is reasonable.
Cheers! :beer: