bhecox65

Hey everyone,

I would like to play an animation with mixing, but have all frames of the animation fully applied instead of the start and end only partially applied due to the mixing. For example: mixing from A to the starting frame of B, play all of B, then mix to C from the last frame of B.

Is there some built in way of doing this that I have missed? Or at least what might be considered the "proper" way to solve this?

Thanks for any help or info! :grinteeth:

---
Here is what I have discovered and tried so far. Please correct me if I am wrong about any of this!
I am using the Unity runtime, but this should be relevant to any of them.

TrackTime
If you subtract TrackTime by the MixDuration, it seems to correctly apply mixing toward the first frame of animation, and once the mix is over it starts the animation as normal.
Mixing out is harder, because that duration is determined by the next animation. If you just add MixDuration to AnimationEnd, it will play the full animation before mixing out, but if mixing with anything outside of the default mix duration it will be incorrect (e.g. if C was a 0 mix duration, B will hold at the last frame for default mix duration). Maybe I can use trackEntry.Next to find the upcoming mix duration? Also, I think HoldPrevious is required here when using higher tracks so there is no snapping to setup/lower pose briefly when mixing out after the animation has ended.

TimeScale
I also tried setting TimeScale to 0, waiting for the MixDuration, and then setting it back to 1. Since mixing is applied without respect to TimeScale, this could sort of work for mixing in. If you needed to actually modify TimeScale though for any other reason, this would break.
This doesn't help with waiting for the last frame to mix out.
bhecox65
  • Messaggi: 2

Nate

Interesting use case! It would be easy if you had an animation that was just the starting frame of B. However, I think you can do it without that by using TrackEntry animationEnd:
state.setAnimation(0, "A", false);

entry = state.addAnimation(0, "B", false, 0.5); // After 0.5 seconds (or whatever you want), mix to B.
entry.animationEnd = 0; // Will play from 0 to 0, ie only the first frame.
entry.mixDuration = 1; // Mix from A to first frame of B over 1s.

// After the mix duration, play B for real, no mix.
entry = state.addAnimation(0, "B", false, 1);

// Once B has played fully, mix to C. Don't pass 0, which takes into account the mix duration.
entry = state.addAnimation(0, "C", false, entry.animation.duration);
entry.mixDuration = 1; // Mix from last frame of B to C over 1s.
Avatar utente
Nate

Nate
  • Messaggi: 12131

bhecox65

Great! Thank you for the quick reply!

That seems to work perfectly! Once I remembered I have a non-zero default mix duration anyway :lol:
I first tried HoldPrevious = true which ends up doing basically the same thing in this case since it prevents mixing out the "mixing B" here, but then realized my mistake and switched to using MixDuration=0.

I have 2 followup questions maybe you can help me with as well: :)

    1) How could I do this from empty on a higher track? The usual method of state.SetEmptyAnimation(upperTrackIndex, 0); makes the "mixing B" not apply or something? It jumps to the first frame of B. Using a tiny delay (like 0.01) on the "mixing B" seems to fix it, but I don't know why or if that's how I should do this.

    2) What should I do if I don't know the next animation yet? E.g. it could either end with B so it should mix back out to empty, probably like state.AddEmptyAnimation(upperTrackIndex, mixDuration, entry.Animation.Duration); Or during B find out I need to mix to C as discussed. I'm thinking add it as normal, but with the delay being the remaining duration? Not sure what to do if there was already the empty animation in the queue though.

Thanks!
bhecox65
  • Messaggi: 2

Nate

Great!

1) Are you calling setAnimation twice? If so, it will nuke the first one if it was never applied. You want setAnimation then addAnimation.

2) If you don't know which animation to queue, you could set a listener for when B is done, then decide at that time to either setEmptyAnimation or setAnimation with C.

If you queue the empty animation and then find out you want C instead, you'd need to get rid of the empty animation. The track entries make up a linked list. You can smoke a queued entry (and all entries after it) using AnimationState clearNext.
Avatar utente
Nate

Nate
  • Messaggi: 12131


Torna a Runtimes