• Runtimes
  • How to disable multipleMixing in spine3.8

  • Изменено
Related Discussions
...

Hey, I'm upgrading our project from 3.5 to 3.8 in unity, and meet a mixing problem.
Blog: AnimationState: multiple mixing without dipping
As this blog say, spine 3.5 has a flag MultipleMixing, when MultipleMixing == false, it's only mix two animations.
I find the code is

private void SetCurrent (int index, TrackEntry current, bool interrupt) {
   TrackEntry from = ExpandToIndex(index);
   tracks.Items[index] = current;

   if (from != null) {
      if (interrupt) queue.Interrupt(from);
      current.mixingFrom = from;
      current.mixTime = 0;

  //from.timelinesRotation.Clear();
  var mixingFrom = from.mixingFrom;

  if (mixingFrom != null && from.mixDuration > 0) {
     if (multipleMixing) {
        // The interrupted mix will mix out from its current percentage to zero.
        current.mixAlpha *= Math.Min(from.mixTime / from.mixDuration, 1);
     } else {
        // A mix was interrupted, mix from the closest animation.
        if (from.mixTime / from.mixDuration < 0.5f && mixingFrom.animation != AnimationState.EmptyAnimation) {
           current.mixingFrom = mixingFrom;
           mixingFrom.mixingFrom = from;
           mixingFrom.mixTime = from.mixDuration - from.mixTime;
           mixingFrom.mixDuration = from.mixDuration;
           from.mixingFrom = null;
           from = mixingFrom;
        }

        from.mixAlpha = 0;
        from.mixTime = 0;
        from.mixDuration = 0;
     }
  }

  from.timelinesRotation.Clear(); // Reset rotation for mixing out, in case entry was mixed in.
   }

   queue.Start(current);
}

our project rely on MultipleMixing == FALSE. But in spine3.8 runtime, I find this logic has changed, it's seem MultipleMixing is always true.

private void SetCurrent (int index, TrackEntry current, bool interrupt) {
  TrackEntry from = ExpandToIndex(index);
  tracks.Items[index] = current;

  if (from != null) {
    if (interrupt) queue.Interrupt(from);
    current.mixingFrom = from;
    from.mixingTo = current;
    current.mixTime = 0;

// Store the interrupted mix percentage.
if (from.mixingFrom != null && from.mixDuration > 0)
  current.interruptAlpha *= Math.Min(1, from.mixTime / from.mixDuration);

from.timelinesRotation.Clear(); // Reset rotation for mixing out, in case entry was mixed in.
  }

  queue.Start(current); // triggers AnimationsChanged
}

Our animation system rely on only two animation mixed, so it's wrong in 3.8 runtime.

I have tried cherry pick old 3.5's logic to 3.8 and play animation, it's works.

So how can I disable multipleMixing in 3.8?

Thanks a lot.

Hmm 3.5 was so long ago, I seem to have lost the brain cells responsible for what multiple mixing was doing. I think that setting should be obsolete now. Can you show the behavior you want and the behavior you get instead?

I play animation a -> b -> c quickly,a -> b,b ->c both have mix.
I just want two animation mixed,a mix c.
Now in 3.8,it's look like a mixed b, c at same time

If you are mixing a -> b and during that mix you play c, then with 3.8+ it will do the a -> b mix and then from that result will mix to c. That usually makes the most sense.

If you are mixing a -> b and during that mix you want to get rid of b and mix a -> c then there should be a way to do that, but when you get rid of b, the pose may jump. There's no way to just cancel the mix to b, but you could clear everything and set a again to the same place it was.

TrackEntry entryA = state.setAnimation(0, "a", true);

// Later: 
state.setAnimation(0, "b", true);

// Later, while still mixing a -> b:

// Get the data from entryA before calling clearTrack, else the entryA could be freed and/or reused.
float trackTime = entryA.getTrackTime();

// Get rid of all entries on the track.
state.clearTrack(0);

// Set a again, at the same time.
entryA = state.setAnimation(0, "a", true);
entryA.setTrackTime(trackTime);

// If we call setAnimation twice without ever applying, it won't mix from the first setAnimation.
state.apply(skeleton);

// Now we can mix to c.
state.setAnimation(0, "c", true);

BTW, I suggest moving to 4.0 rather than 3.8.