• Runtimes
  • Mixing fail in cocos2d-x

  • Đã chỉnh sửa

Hi!

Today, I have update my runtime to latest version on Git (2.5 up from 2.3). Everything was working fine before the update but now my code for mixing animations seems to be broken (code that I did like a year ago). Please, take a look:

void runAnimation(SkeletonAnimation *skeleton, int trackIndex, const string &animation, bool loop, bool mix, float mixTime)
{
    string current = "";
    spTrackEntry *entry = skeleton->getCurrent(trackIndex);
    if(entry != nullptr)
        current = entry->animation->name;

if(current == "" || !mix)
{
    skeleton->setAnimation(trackIndex, animation, loop)
}
else
{
    skeleton->setMix(current, animation, mixTime);
    skeleton->setAnimation(trackIndex, animation, loop);
}
}

Currently, it seems that setMix function is not working as intended because it is interpolating between the setup pose and 'animation' instead of doing it between 'current' and 'animation'. I want to clarify again that my code was working prior the update. Please, can you take a look and tell me if this is ok? In case it is working as intended, can you explain me how my code should look?

Thanks in advance!! 🙂

Regards,
fryderyk


Hi again!

I have noticed another rare behaviour after updating.

We have a character that has a run animation (which moves the right arm) playing on trackIndex 0, I will call it "A" animation. When there is some user input, it plays a right arm animation on trackIndex 1, I will call it "B" animation. Before the update, everything was working as I expected. The A animation plays correctly, then a B animation is triggered by user which overrides the A animation for the right arm (because it has a greater index) and when the B animation is finished, the right arm recovers its animation from the A animation.

However, after updating, when B animation finishes, the right arm doesn't keep playing A animation anymore. The arm just keeps the state of last keyframes of B so the right arm doesn't move anymore by A animation. I don't know if the new AnimationState is built to work like that or there is any bug concerning this... like I said in the first post, if the new behaviour is correct, can you tell me how can I reproduce the old one?

Thanks in advance!! 🙂

Regards,
fryderyk

The effects you see are "intended" but lead to what is called the dipping problem. See [runtimes] Fix AnimationState dipping problem · #815 for links to forum threads and information.

We've since changed to behaviour in the 3.6-beta branch of the runtime repository. You can now either have the old behaviour of just mixing between enqueued animations (default), or "mix to setup pose" behaviour. I'll likely finish the port of this to spine-c and hence spine-cocos2dx today in the 3.6-beta branch. See this issue on the status of the port [runtimes] Port dipping problem fix · #867

One I'm done with the port, you can update your runtime to the 3.6-beta branch version, which is compatible with exports from Spine editor version 3.5.x. This should fix both the original issue and the second issue you mentioned.

Ohh I see, so now we have a more powerful AnimationState. That's nice!

Eagerly waiting for the commit to choose between behaviours, so we will be able to switch to the old one and not having to rework anything. Keep up the good work!! 🙂

Regards,
fryderyk

The 3.6-beta branch now contains the modification. You can disable multiple mixing via spAnimationState->mixingMultiple = 0 (enable with a value != 0). It's off by default, while the 3.5 version has it on by default (which is the only option there). Let us know how it works out for you!

Good and not so good news.

First issue has gone, yoohoo!

Second issue is still there. I have commented the setMix line (so there is no mixing at all) and the problem continues so it is not a problem about the setMix function. Any ideas?

Thanks!!

Regards,
fryderyk

AnimationState behavior is different in later runtimes. When you play an animation, it continues to be applied, even if it doesn't loop. See TrackEntry trackEnd for details. Set trackEnd to the Animation duration if you want the old behavior, or call AnimationState addEmptyAnimation to mix out the animation when it is complete.

Thanks Nate! That's exactly what I needed. Sorry for misundertanding the new API 🙁

Anyways I can see a bit of flickering between animations if I do

entry->trackEnd = entry->animation->duration;

I tried with this

entry->trackEnd = entry->animation->duration + 0.1f;

and the flickering disappeared but it's more a nasty workaround than a nice solution... Do you have a cleaner way to do it?

Again, I have to thank all Spine team for the nice support to us developers 😉
Good job mates!

Regards,
fryderyk

Glad that helped. 🙂

Can you describe what flickering you see? Between what animations?

Sorry for the delay Nate, weekend is sacred for me! 😃

I have to record it with my phone because it is only a frame but the setup pose can be seen between animation "A" and "B" if I run this code:

spTrackEntry *entry = skeleton->setAnimation(index, "A", false);
entry->trackEnd = entry->animation->duration;
skeleton->addAnimation(index, "B", false);

The result is: A plays correctly, setup pose plays for 1 frame, B plays correctly.

I know the second line is not necessary in this case but this is a simplified version of my code. On real version, when A animation is set to play, I don't know if a B animation is going to be played so I must be sure that track is cleared when A animation is done (if not I have the "fixed arm" case I explained on the other post).

Any ideas?

Regards,
fryderyk

From TrackEntry trackEnd:

If the track end time is reached, no other animations are queued for playback, and mixing from any previous animations is complete, then the properties keyed by the animation are set to the setup pose and the track is cleared.

You are seeing that situation when you shouldn't: A hits trackEnd but shouldn't be set to the setup pose since you have B queued to play after A. We've fixed this in the spine-libgdx reference runtime:
Don't use setup pose for last apply when there is a next animation.@47155e4
You can apply this fix yourself (line 160 is all that is needed, the other part of the diff is just formatting), else we will soon port it to all runtimes in the 3.6-beta branch and it will make its way to master when 3.6 is released.

Thanks Nate!! That fix seems to solve all my animation issues! 🙂

Regards,
fryderyk

The fix is also in the 3.6-beta branch!