• Runtimes
  • IK Mix over Multiple Animations in Quick Succession

Related Discussions
...

Hello,

I am seeing some strange behaviour regarding the IK Mix when I play a few animations in quick succession.

My final animation the IK Mix isn't keyed, and in the setup pose, the Mix is 0. other than that, in all of the animations, the mix is keyed on frame 0 to 100.

The problem is, the IK Sometimes remains with the mix of 100 during the final animation. This doesn't always happen, and my money is on it is something todo with the blend between animations (using term blend here because I'm using the term mix for IKs).

Here is a log of what happens when the IK Remains on

Animation 1 Plays (looping) Time: 69.52
Animation 2 Plays, Time: 73.61
Animation 1 Plays (looping) Time 73.71
Animation 2 Plays, Time: 73.73
Animation 3 Plays, Time: 73.76  (IK mix not keyed in this animation)

(animation 1 has a 1 second duration)

However a timeline like this does not keep the IK Mix to 100:

Animation 1 Plays (looping) Time: 7.44
Animation 2 Plays, Time: 12.51
Animation 1 Plays (looping) Time 12.61
Animation 2 Plays, Time: 12.64
Animation 3 Plays, Time: 12.75  (IK mix not keyed in this animation)

You wouldn't happen to be able to help a guy out with a repro case, would you?

I have you one 🙁
All animations are setanimation above, rather than queued
Ill see if I can change the goblins spine file


BinaryCats wrote

I have you one 🙁
All animations are setanimation above, rather than queued
Ill see if I can change the goblins spine file

:S :wonder: :doh: 😢 doesn't happen in my test case (yet)


After looking at the spine events, it seems the end event of Animation1 and Animation2 are happening After the Start event of Animation3

Image removed due to the lack of support for HTTPS. | Show Anyway

I'm not sure what else I can give you, mayve I have given you too much already


CONFIRMED! ITS @PHARANS FAULT! 😉

Blend Weirdness in Unity 3.5?

This code breaks it.

Before that code change:

Image removed due to the lack of support for HTTPS. | Show Anyway

after:

Image removed due to the lack of support for HTTPS. | Show Anyway

using attached file


Animationstate.SetAnimation(0, "Animation1", true);
 yield return new WaitForSeconds(1.5f); //wait for 1.5 seconds
 m_Animation.state.SetAnimation(0, "Animation2", false);
 yield return null;//wait for one frame
 m_Animationstate.SetAnimation(0, "Animation1", true);
 yield return null;//wait for one frame
 m_Animationstate.SetAnimation(0, "Animation2", false);
 yield return null;//wait for one frame
 m_Animationstate.SetAnimation(0, "Animation3", false);


It's not my code. I just ported Nate's changes to C#. :p

Thanks for the repro case though, and for identifying that it's a bug in the experiemental AnimationState.

No, it's all Pharan's fault. He shall self-flagelate for a week!

11 days later

No news yet. Fix will be part of the dipping issue fix we are working on. Which is hard :/

4 days later

:smoke: :smoke: :smoke: :smoke: :smoke: :smoke: :smoke:

So, I have been doing some investigating, and have some suspicions of how this bug occurs.

It all starts with the private float ApplyMixingFrom(TrackEntry entry, Skeleton skeleton) function. we where able to produce a repo case and concluded that For IKs setupPose variable can be evaluated incorrectly. setupPose is set like thisbool setupPose = timelinesFirstItems[i];) wheretimelinesFirstItems = from.timelinesFirst.Items;`

timelinesFirst is set up in the function

private void CheckTimelinesUsage(TrackEntry entry, ExposedList<bool> usageArray)
{
    var propertyIDs = this.propertyIDs;
    var timelines = entry.animation.timelines;
    int n = timelines.Count;     //var usageArray = entry.timelinesFirst;
    usageArray.EnsureCapacity ;
    var usage = usageArray.Items;
    var timelinesItems = timelines.Items;
    for (int i = 0; i < n; i++)
        usage[i] = propertyIDs.Add(timelinesItems[i].PropertyId);
}

If the IK is already in usageArray (i.e. timelinesFirst) it will get flagged as false, and therefore the animationstate, will think it doesn't need to do set up pose mix.

But how can it already be in the list? I suspect that it is because an IK can be keyed in two different ways, The first way being the target transformation and the second way would be the mix. So it would make sense for it to be in the list twice, but I think they have the same propertyID. So when the mix checks if it is the first, it see there is a transformation key and then gets flips to false.

Does this make sense?>

We hacked in some code to make the IK think it was from setup pose, and it solved these issues.

Thanks bcats. Quickly checked what values it was pushing to the propertyIDs collection and it seems to be normal.
Could have been a problem if it was passing the same IDs for two different things. But that wasn't it.

We'll have to add this info to the issue.

5 days later

Hmm

So I guess the question is: should 'setuppose' in apply mixing from be true for Animations with mix time 0.
our repo was:
Setup pose - ik mix = 100
Play Animation which keys mix to 0 frame 0
Interrupt that animation with animation which DOES NOT key the mix, (it keys the transform or ik)

The ik mix is still 0.

Should it be 100 because that is what it is in setup pose?


I have confirmed that atleast 3 animations need to have been played. just playing two animations, do not seem to recreate the bug.


https://drive.google.com/file/d/0B5ElW0WUt28eWFVpcXNnTXF4TFU/view?usp=sharing

Ok. I have reduced the problem into its simplest form. Above is a unity project (sorry nate, its the easiest way of showing you the problem) with the issue (please note all playing of animations is done within the IKBug.cs file).

Within the project there is a modified Goblins.spine file. With 2 animations. The first animation Anim1 keys the IK mix to 0. The second animation Anim3 (sorry about the name), doesn't key anything.

The following code is what happens to the animation state, with animations being set. If you are unfamiliar with co-routines, yield return null means wait one frame - Although it is possible for this bug to happen at different stages of animations, its hard to reliable timing for that.(if it loops maybe?) .

    private IEnumerator PlaySpinAnimation()
    {
        yield return new WaitForSeconds(0.5f);//Wait for a second to start playing the animation

    //Anim1: Keys IK to 100
    //Anim3: empty animation - no keys


    //True - IK Mix will end up as  0
    //False - IK Mix will end up as 100
#if true 
        m_Animation.state.SetAnimation(0, "Anim1", true);
        yield return null;
        m_Animation.state.SetAnimation(0, "Anim1", true);
        yield return null;
        m_Animation.state.SetAnimation(0, "Anim3", true);
        yield return null;
#else
        m_Animation.state.SetAnimation(0, "Anim1", true);
        yield return null;
        m_Animation.state.SetAnimation(0, "Anim3", true);
        yield return null;
#endif
        Debug.Log(m_Animation.skeleton.ikConstraints.Items[0].mix);
    }

setting the #if to True, will make the IK Mix = 0. Setting it to False results in IK Mix = 100.

  1. Some notes:

  2. Setting the default mix to >0, results in IK Mix = 1, no matter which code path.

  3. #if true 
            m_Animation.state.SetAnimation(0, "Anim1", true);
            yield return null;

    the yield return null; here (and only here) can be replaced with yield return new WaitForSeconds(10 // doesnt matter what this time is. As it does not matter how long before the second animation, Anim1 started.

  4. I play Anim1 twice, but it doesn't matter what anim plays, so long as it keys the IK off


:smoke:

Not been ignoring you, just not having the capacity at the moment. I'll get to this asap. Finishing up Spine Lua runtime 3.6 port first. Sorry for the wait :/

I'm checking this out.

FYI, there's no need to include the Library folder in your project when you share it.
Unity can rehydrate that from scratch, and Library usually contains disproportionately large files compared to your essential project files.


This is a really weird project. Why does it contain examples from version 1.x and 2.x?

Anyway, try this new one: https://gist.github.com/pharan/cffdc3b2aee9288c9ca8b4ab94ee97d2
I just sorta handled the case where the MixingFrom Timeline Apply was a last-frame-mixing-out or any of the alphas are 0.
I'm not sure if this causes some problems for other cases.

@badlogic @Nate At this point, the experimental C# version diverges from the experimental libGDX one.

I was going to suggest if the mix = 0, then always use the setup pose. But I wasn't sure if this would solve the problem at the root of it 🙂.

Why does it contain examples from version 1.x and 2.x?? huh what do you mean? like the spine examples? i use this directory when testing out all spine bugs.

And I know I don't need to include the lib folder, its just it takes ages to recreate one, and I'm trying to be helpful 🙂


oh, and applying this fix, does seem to fix the issue and other minor visual glitches we where getting

It didn't take long. Like a minute for this one.
It takes ages if you have many giant assets, I suppose. Still not worth uploading giant files, IMO. Especially with bandwidth caps these days.

It was logging incompatible skeleton warnings when it tried to load the sample jsons.

The fixing minor visual glitches part sounds good. 😃
I did good, Nate. :p