• Runtimes
  • Blending animations in Solar2Dwith setEmptyAnimation

  • संपादित
Related Discussions
...

Hi!

I'm setting/adding animations successfully on track 0 using the Spine Library in Solar2D. But I don't understand the concept of an "empty" animation, and I am having trouble understanding how to blend between any two of my animations. I have read the docs on setEmptyAnimation (http://esotericsoftware.com/spine-api-reference#AnimationState-setEmptyAnimation).

As I understand it, the following pseudocode should blend smoothly from a "walk" animation on track 0, to a "run" animation on track 1, and then to "jump", a different animation which replaced "walk" on track 0.

animationState.setAnimationByName(0, "walk", -1) 

---

start walking forever (-1 loops)
wait(5) 

---

let it walk for 5 seconds
animationState.setAnimationByName(1, "run", -1)  

---

tell the animation to play "run" on track 1 forever (-1 loops)
animationState.setEmptyAnimation(1,  2) 

---

take 2 seconds to mix to track 1, where "run" is playing
wait(3) 

---

wait for 3 seconds, meaning it will be completely in the "run" animation for 1 second, because of the 2 second mixTime
animationState.setAnimationByName(0, "jump", -1)  

---

track 0 will now play "jump", not "run"
animationState.setEmptyAnimation(0,  .2) 

---

take .2 seconds to mix to track 0, where "jump" is playing

This doesn't seem to work as intended. Should it?

I can't tell exactly what the "setEmptyAnimation" does. What does "empty" mean? Is it the track that is currently not playing? Or the one that is currently playing, but that will be "empty" because you're mixing out from it? I'm confused. Help!

Here's the function I've currently got which I think should do this correctly (it's in Lua). It alternates between track 0 and 1, with whatever animation you request:

local playOnZeroTrack = true
function spineObject:blendToNewAnimation(animationName, mixDuration, loops)
       local emptyTrack = playOnZeroTrack and 0 or 1
       local newTrack = playOnZeroTrack and 1 or 0
       animationState:setAnimationByName(newTrack, animationName, loops)
       animationState:setEmptyAnimation(emptyTrack, mixDuration)
       print("Empty animation set to track ", emptyTrack, "new animation set to track ", newTrack )
       playOnZeroTrack = not playOnZeroTrack
end

With this code, it blends smoothly to an animation on track 1, but when I try to go back to track 0, it snaps and goes immediately. How do I get it to go both ways? Is this possible with only two tracks? why not? Here's a video showing what the above code does.

An empty animation is an animation without any keys. This means it represents the setup pose of your skeleton. If you mix from an animation like "run" to an empty animation, then you mix the run animation back to the setup pose.

You do not need to use setEmptyAnimation() to mix two animations. Let's say you have setAnimationByName(0, "walk", true), so the skeleton walks indefinitely.

Now you want to switch to the "jump" animation. All you need to do is to setAnimationByName(0, "jump", true), which will mix out the walk animation and mix in the jump animation.

The duration of the mix is defined in the AnimationStateData you passed to AnimationState when you created the latter. Alternatively, you can set the mix duration on the Track that is returned by setAnimationByName.

Thanks, Mario! I understand more clearly now. That setMix function in animationStateData is a real help, but I didn't see a reference to it anywhere when searching about how to mix things up.

If I understand correctly, though, I think there's a small problem with the Corona implementation. I have gotten it working, but I needed to change the way the animation mix times were referenced. In the AnimationState class, this:

entry.mixDuration = data:getMix(last.animation, animation)

needed to change to this:

entry.mixDuration = data:getMix(last.animation.name, animation.name)

When I do this, it works properly, since when I set the mix, I'm not setting animations, but animation names, right? In lua, I can't set the key of a table to be another table.

One question about the setEmptyAnimation function, now


is it just what the spine objects mixes back to when animations on other tracks have finished? If so, let's say I

setEmptyAnimation(0, 1)

, and then

setAnimationByName(1,"walk", false)

. Does this mean that it will do one cycle of the "walk" animation, and then take one second to mix back to whatever keyless pose (probably just the character standing) is in track 0?

Regarding the mix durations, you don't have to set the entry.mixDuration! Simply set the mixes on the AnimationStateData that you give to the AnimationState by name, e.g. data:setMix("walk", "jump", 0.2). The AnimationState will then take care of mixing the animations as specified.

Regarding the empty animation: you want to call setAnimationByName(0, "walk", false) then addEmptyAnimation(0, 0). This queues 2 animations on track 0 of the AnimationState: the "walk" animation, and the empty animation (which is equal to the setup pose of your skeleton). The AnimationState will then playback the "walk" animation once, then mix it out to the empty animation, i.e. setup pose.

Mario, thanks for the response again


sorry for my long delay! I'm not trying to modify entry.mixDuration


I saw that that information comes from the

setMix

function. But the

setMix

function from esoteric's side seemed to have a bug, where you couldn't give the AnimationState by name, as you've suggested. The code change I made to fix this perceived bug is in my previous comment. I think it was just a problem that happened when converting the library to Lua.

Thanks for explaining everything! Very clear.

This is now fixed in both the 3.8 and 4.0-beta branches.