- Home /
What am I not getting about animation weight blending?
I've been having difficulty getting animation blending to work, so I've created a simple example. Can someone please explain what I'm doing wrong?
Assume there are two animations on a character... "walk" and "zombie". (Why zombie? Why not zombie? It's Halloween.)
Here is code:
function Start () {
animation["walk"].layer = 2;
animation["walk"].weight = 1.0;
animation["zombie"].layer = 3;
animation["zombie"].weight = 0.5;
animation.Play("walk");
animation.Play("zombie");
}
By my understanding, this should play zombie at half weight and walk at half weight, but instead, it plays zombie at full weight. Why?
EDIT: To further describe, let's say I change my code to this:
function Start () {
animation["walk"].layer = 2;
animation["walk"].weight = 0.5;
animation["zombie"].layer = 2;
animation["zombie"].weight = 0.5;
animation.Play("walk");
animation.Play("zombie");
}
Even when I do that, it still plays the "zombie" animation at full weight instead of evenly distributing them. Does anyone know why that might be?
EDIT #2: Changing the order of the animations makes a difference. If the "walk" animation is set to play after the "zombie" animation, the "walk" animation will play instead, at 100% weight.
Still, this doesn't solve the overall problem of making them blend 50-50.
To solve the problem of gettin 50-50, you need to set top layer to 50% and bottom layer to 100% (it will get the 100% of the 50%, like stated in the wiki page)
Answer by Bunny83 · Oct 29, 2012 at 08:06 PM
Each animation layer is handled seperately. A higher layer number has a higher priority. The highest layer is "served" first. When it doesn't use all weights, the lower layers get their part of the remaining weight.
See the blending weight page.
Also the blend weights are always normalized. When you have two animations on the same layer, one with 1.0 and one with 0.5, the first one will get 0.66666 and the second 0.33333. In this case this layer eats up 100% of the weight.
Here's another example:
Animation layer blendweight resulting weight
anim1 1 0.2 0.2 ---> remaining weight
anim2 1 0.3 0.3 ---> == 0.5
anim3 0 4 (== 0.4) 0.2 (== 0.5*0.4)
anim4 0 6 (== 0.6) 0.3 (== 0.5*0.6)
$$anonymous$$y highest layer is layer 3, and it should take half of the weight. The other layer is 2, and it should take the remaining half, right? So why would the zombie animation play at full if they should be evenly distributed?
And even if I put both animations on the same layer, and with the same weight of 0.5, the animations still aren't blended. Is there a setting I'm missing?
Like you figured out, Animation.Play does two thinge (or three):
It enables the AnimationState and rewinds it when it's not playing at the moment.
It sets the blendweight to 1.0
It eventually stops other animations depending on the second parameter (Play$$anonymous$$ode).
CrossFade does almost the same, but it keeps the old animation playing and "lerps" the blendweights over time.
You don't need to use the Play or CrossFade function at all. When you want full control of your animations, just:
See the AnimationState class for more information.
THIS! THIS IS WHAT I NEEDED!
I wish I could have had the above paragraphs about two years ago. It would have saved me so much confusion.
To answer your two edits in your question:
Edit1: This doesn't work because both animations are on the same layer and the default parameter for Play() is Play$$anonymous$$ode.StopSameLayer. When you use the Play function, only one animation per layer is allowed.
Edit2: Sure, when you change the order the other animation will play ins$$anonymous$$d. Only the "last call" will take effect.
The moment you said "It sets the blendweight to 1.0" it all made sense, but thanks for clarifying. That's what I needed to know in the docs. (Animation.Play() does not seem to mention that little detail.)
Answer by whydoidoit · Oct 29, 2012 at 07:59 PM
Higher layers get the weight first - so it get a much higher proportion. Putting them on the same layer with the same weight would give you half of each. The weights are kind of added up with to get the final proportion. Basically all of it goes to the higher layer.
Answer by Screenhog · Oct 29, 2012 at 11:02 PM
Finally found a fix. I had to set the weight of the animation AFTER playing it.
function Start () {
animation["walk"].layer = 2;
animation["zombie"].layer = 3;
animation.Play("walk");
animation["walk"].weight = 1.0;
animation.Play("zombie");
animation["zombie"].weight = 0.5;
}
Unfortunately, I guess this means that I'll have to set the weight manually each time. But at least it now makes sense.
Answer by OLGV · Sep 10, 2013 at 02:41 PM
I have a question on this... if I have 20 animation files (rotate, move, etc) and the 21th that animates just the intensity (spot light), how could you make layer 1 applying for any animation file on the object... so I can turn them all on and off no matter of what other motion animation is happening around...
I am trying to avoid making a separate scripts for each animation file..
would something like this work?
function Start () {
animation["walk, walk2, walk3, walk4"].layer = 2;
animation["zombie"].layer = 3;
animation.Play("walk, walk2, walk3, walk4");
animation["walk, walk2, walk3, walk4"].weight = 1.0;
animation.Play("zombie");
animation["zombie"].weight = 0.5;
}
or other way of not listing all the animation files..
thanks