• Runtimes
  • Issues with 'setToSetupPose'

  • Modificato
Related Discussions
...

My character has 2 animations (Idle and Run) and I'm not using the skin sub-system.

When the character is running I key( is that the term?) an attachment on its left leg and tilt the body forward. Every time the animation is changed I call skeleton:setToSetupPose(). However, the attachment on its left leg don't change back to the original one.

... code here...
if animationChanged then
   if self.currentAnimation == 'standing' then
      state:setAnimationByName(0,'idle',true)
   elseif self.currentAnimation == 'moving' then
      state:setAnimationByName(0,'run',true)
   end
   
skeleton:setToSetupPose() end skeleton.x = self.x skeleton.y = self.y state:update(dt) state:apply(skeleton) skeleton:updateWorldTransform()

I also tried to call skeleton:setToSetupPose() before setting the new animation, but nothing changed.


Here we can see the body clearly tilted forward and the attached left leg.


And here's the character idling after the running animation is stopped/interrupted.

How do I fix this? And if I was using skins, would the solution be the same?

Skins should not matter for this. In fact, at runtime all attachments are stored in a skin. If an attachment was not in a skin in the editor, it is in the "default" skin. The code in question is here:
spine-runtimes/Slot.lua at master
data.attachmentName is the name of the attachment in the setup pose. What is attachmentName for the left leg SlotData? skeleton:getAttachmentByIndex looks in the skeleton's skin and if not found looks in the default skin. The code for this looks correct.

What runtime are you using? Are you using the latest? Since 3.5 you no longer need to call setToSetupPose when changing the animation. AnimationState mixes animations out so they don't leave the skeleton in the state from the last time the animation was applied.

If you're using Spine 3.5, you shouldn't need the call to setToSetupPose here anymore.
In fact.. hmmm... I'm not sure if it might actually break stuff.
It shouldn't, theoretically.

Nate ha scritto

What runtime are you using? Are you using the latest? Since 3.5 you no longer need to call setToSetupPose when changing the animation. AnimationState mixes animations out so they don't leave the skeleton in the state from the last time the animation was applied.

I'm using spine-love + spine-lua runtime.

I generated the .json and .atlas files after updating my spine to the latest version, and I downloaded the runtime libs from this link on github (https://github.com/EsotericSoftware/spine-runtimes/archive/master.zip) yesterday night.

Here's what happens when I change the animation from 'run' to 'idle' without calling setToSetupPose:

Note that all bones are on the correct position for the idle animation, but the whole body is tilted forward because I rotate the root bone to create the running animation and it is not rotating back to default position unless I call setToSetupPose.

The only manipulations I'm doing on the skeleton and state are the ones shown on the code snippet I posted before.

Did you remember to copy /spine-lua/* into /spine-love/spine-lua/?

Again, what is attachmentName for the left leg SlotData? What happens in Slot setToSetupPose?

Nate ha scritto

Did you remember to copy /spine-lua/* into /spine-love/spine-lua/?

Again, what is attachmentName for the left leg SlotData? What happens in Slot setToSetupPose?

Yes, I have both libs correctly setup on my project. I thought that was the case, tried to move the folder and the game didn't even booted. My current structure is:

  1. Project/

    1. spine-lua/
      spine-love/
      main.lua

I "modified" setToSetupPose to print the attachmentName and index as follows:

function Slot:setToSetupPose ()
   [...]
   print(data.index..'  '..data.attachmentName)
   if data.attachmentName then
      attachment = self.bone.skeleton:getAttachmentByIndex(data.index, data.attachmentName)
   end
   [...]
end

and everything seems to be ok:

1  left_arm
2  left_hand
3  left_thigh
4  left_foot
5  left_leg
6  right_foot
7  right_thigh
8  right_leg
9  abdomen
10  chest
11  head
12  right_arm
13  sword
14  right_hand

This was the same result every time setToSetupPose was called (every time the animation changed).

Investigating further, I also modified setAttachment to print the attachment name

function Slot:setAttachment (attachment)
   print('set '..attachment.name)
   if self.attachment == attachment then return end
   [...]
end

Here is my output

calling state:setAnimationByName [run]
< called state:setAnimationByName [run]

calling skeleton:setToSetupPose
set left_arm
set left_hand
set left_thigh
set left_foot
set left_leg
set right_foot
set right_thigh
set right_leg
set abdomen
set chest
set head
set right_arm
set sword
set right_hand
<< exiting skeleton:setToSetupPose

/* This is the expected behaviour. Changing attachment while running, so both legs look identical */
calling state:apply
set right_foot
set right_leg
<<< called state:apply
calling state:apply
set right_foot
set right_leg
<<< called state:apply
calling state:apply
set right_foot
set right_leg

[...]

/* Stopped running */
calling state:setAnimationByName [idle]
< called state:setAnimationByName [idle]

calling skeleton:setToSetupPose
set left_arm
set left_hand
set left_thigh
set left_foot
set left_leg
set right_foot
set right_thigh
set right_leg
set abdomen
set chest
set head
set right_arm
set sword
set right_hand
<< exiting skeleton:setToSetupPose

/* Buggy behaviour */
calling state:apply
set right_foot
set right_leg
<<< called state:apply

Thanks, that helps a lot. If I understand correctly:

  • You set the animation to run, which keys right_leg to be used for the left leg slot.
  • You set the animation to idle and call setToSetupPose, which sets the left leg slot to left_leg.
  • When AnimationState is next applied, something (the run animation being mixed out?) sets the left leg slot to right_leg.
  • Expected behavior: After setting idle (with or without calling setToSetupPose) and then applying the AnimationState, the left leg slot should be set to left_leg.

Is there a mix duration between run and idle?

What is supposed to happen is when run is no longer applied, anything it keyed is set back to the setup pose. This would result in the left leg slot using left_leg, even without calling setToSetupPose. When run is being mixed out (even if it has a mix duration of 0 it mixes out over 1 frame), it should not be setting the left leg slot to right_leg unless TrackEntry attachmentThreshold is > 0. Likely there is a bug in AnimationState. :tmi: We'll dig into deeper first thing Monday morning.

Nate ha scritto

Thanks, that helps a lot. If I understand correctly:

  • You set the animation to run, which keys right_leg to be used for the left leg slot.
  • You set the animation to idle and call setToSetupPose, which sets the left leg slot to left_leg.
  • When AnimationState is next applied, something (the run animation being mixed out?) sets the left leg slot to right_leg.
  • Expected behavior: After setting idle (with or without calling setToSetupPose) and then applying the AnimationState, the left leg slot should be set to left_leg.

Is there a mix duration between run and idle?

What is supposed to happen is when run is no longer applied, anything it keyed is set back to the setup pose. This would result in the left leg slot using left_leg, even without calling setToSetupPose. When run is being mixed out (even if it has a mix duration of 0 it mixes out over 1 frame), it should not be setting the left leg slot to right_leg unless TrackEntry attachmentThreshold is > 0. Likely there is a bug in AnimationState. :tmi: We'll dig into deeper first thing Monday morning.

Yes, that's exactly what's happening.

I didn't change the mix duration between animations. I will read the docs a bit more and change it to 0 to see what happens. I will also check the attachmentThreshold.

Thanks for everything.


badlogic ha scritto

Could you provide me with your exports? Send them to contact@esotericsoftware.com. Thanks!

Hi, files sent 🙂

Thanks for the all the info. This is now fixed in the latest master branch commit on the Spine Runtimes git repository. Please update and let me know if everything is good on your end now.

badlogic ha scritto

Thanks for the all the info. This is now fixed in the latest master branch commit on the Spine Runtimes git repository. Please update and let me know if everything is good on your end now.

It works like a charm!

Thanks to all of you for being so responsive and helpful :party: !


Oh, I forgot to mention. After the update, setToSetupPose is, as intended, no longer needed to restore the bones rotation

Cool!