- Home /
Changing AnimationState weights does screw up Crossfading..
Hello, I just realized by trials and errors that changing AnimationState weights on-the-fly (= outside of Update/LateUpdate loops) does completely screw up any Crossfading based on the ones you changed.
Ex (pseudo code) : Objective : Sample a transform value from the animation I'm going to Crossfade with Anim1
1) Play(Anim1)
2) change the weight of Anim2 and then Animation.Sample() it
3) Now that Anim2 weight is 1f, Anim1 weight is automatically normalized to 0f,
4) So I have to change Anim1 weight back to 1f, in order to have Anim1 display correctly again
5) Then, launch a Crossfade(Anim2) from Anim1
Result : the crossfading goes completely weird... weird rotations, placements, etc, just as if Anim2 failed to calculate the shortest rotations from Anim1
The only explanation I find from this behaviour is because Quaternion from Anim1 were reset during the Sample() process, therefore Anim2 can't find a logical follow-up to each animated transform.
So, how are we supposed to deal with mixing Animation.Sample() and Animation.Crossfade() ?
Answer by n0mad · Sep 30, 2011 at 08:14 PM
Ok, I found a workaround (I've created the question today, but been working on it for days). But it's a very weird workaround ...
Basically, for any Crossfade to not go south after having performed an Animation.Sample(), you have to set the old anim back by specifying its state vars (weight, time, etc) twice.
Yup, twice : one AnimationState where you put back your old anim to full weight, then Sample() again, and then one another AnimationState where you put the weight/time/enabled values you had before sampling another animationClip.
Explanation : So let's take again the example from the first post, where I want to sample a transform from Anim2, but while I'm reading Anim1.
The right thing to do is :
0) Save all Anim1 animationState values (weight, enabled, time, etc)
1) disable Anim1
2) put Anim2 on full weight (1f) and enable it
3) Animation.Sample() and pick the values you want from it
4) Disable Anim2
5) put Anim1 on full weight (1f), its initial normalizedTime (forced to 1f if Anim1 was already over), and enable it
6) Animation.Sample() to make the main Animation go back to the state it was before 1)
7) put Anim1 on the values you saved in 0)
And it works. No Crossfade weird stuff. I found this by analyzing, digging and trial/erroring for days, so I'm quite happy, but the negative point is ... how the hell was I supposed to know that ??
For short, here I have to "fake" the Anim1 transforms to a fully weighted state, send it to the player, and then put it back to its original saved weight, even if it was 0f.
Isn't it completely counter intuitive ? I can understand the technical reasons behind such a maneuver, but it doesn't feel right, as anybody who faces the problem will have to trial and error like me to reach that solution.
Isn't it a bug ?