|
I'm familiar with animation blending and mixing systems, and have written several for various game engines in the past. Lately I've been working with Unity's animation system, and I have found the design throughly confusing. The documentation is, as with many other areas, correct but quite lacking in technical detail. Additive animations seem particularly difficult to use for any case other than the "lean left / right" sample that is included with the docs. Here I'll summarize my understanding of the system. Combining animations is a common problem. We'd like to have, say, a run, a punch, and a running punch, and it would sure be nice if the running punch could be generated by blending the run and the punch together so that the punch takes over a subset of bones (probably the upper body). Unity can do this easily with AnimationState.AddMixingTransform(), which allows you to specify a subset of a skeleton for an animation to control. In combination with layers, you can then play two animations simultaneously and have one control the blend weights for some bones and the other control the blend weights for other bones. Great. The problem with this is that you need to know which bones are influenced by the animation. You must hard-code the names of these bones, and perhaps the path through the hierarchy to reach them, into your script so that calls to AddMixingTransform() are effective. In a game with lots of animations in which the animator needs to be able to modify and create content without the constant involvement of a programmer, this is an unacceptable dependency. The other way that Unity enables animation combination is via additive animations. In this case, you specially prepare an animation such that the first frame is a "reference" pose (which should be the bind pose, I guess; that's how the Character Animation sample with lean left and lean right works). When an animation is marked as additive, Unity calculates the delta between the first frame pose and all subsequent poses. That means you don't have to manually hard-code the names of all animated bones. Hooray! Except that additive animations ALSO seem to change the way that layers are blended. The documentation says,
(my emphasis). The problem is that "apply" does not mean "calculate a weighted blend as normal." It's not clear exactly what it means, but the output looks a whole lot like a weighted add where the additive animation is given 50% weight and all subsequent layers fill in the remaining 50%. This is true even if the additive animation's weight is set to 1.0. Here's an example. Say we have a character with two animations, a run and a punch. Run is on layer 0, and is a normal blended animation. Punch is on layer 1. We set punch to enabled, weight 1.0, play type clamp forever. If we play this animation with AddMixingTransform() and manually specify the bone at which Punch should take over, it works as we expect; the bones controlled by the Punch animation get 100% of the blend weight (because the Punch weight is 1) and the rest of the bones are animated at 100% blend weight by Run. Now we modify Punch so that the first frame of the animation is the bind pose. And we remove AddMixingTransform() and change the blend type to Additive. We leave the blend weight at 1.0. In this case, I would expect Unity to use the first frame to calculate delta rotations for all subsequent frames, subtract that delta from the animated output, and then blend the resulting bone matrix normally based on the layer and the animation's blend weight. What (apparently) happens instead is that the Punch animation is only given 50% contribution to the blend weight. Perhaps that's what "additive" means, but it is extremely counterintuitive. Why can I specify the blend weight if it will be ignored? (Actually, in this case, the blend weight is not ignored; setting it to something less than 1.0 gives less than 50% contribution). Other than the lean left / right case, which is exceedingly simple (only one bone is moving!), I don't see how this behavior is useful for combining animations. This system should allow me to completely overwrite animation on certain bones while ignoring other bones; ideally it would use the delta between the first frame of the animation and subsequent frames to automatically figure out which bones to call AddMixingTransform() on. Then you could generate current behavior just by setting the weight of the additive animation to 0.5. So, before I go write up a feature request for this: have I understood the system correctly? Is there a way to use additive animations such that I can blend partial-skeleton animations in and out without having to manually specify the names of the bones that should be influencing the model? Is the behavior I'm seeing correct output or the result of a bug? Thanks.
(comments are locked)
|
|
Hmm, we don't used additive animations yet, but i have to admit that some things are not that well explained. However the 50% / 50% thing is more or less explained here:
I don't have that much experience with additive animations, but from what the docs say i would suggest that you can't play an additive animation as standalone animation. It just applies relative motion so it needs a base on which it's operating. If you put an additive animation on a seperate layer and it's the only animation on this layer the result would be garbage. I guess Unity ignores the layer in this case but as i said haven't tried somethin glike that yet ;) It's just what i can "read" out of the docs. edit I just made two small animations (inside Unity I'm just a coder ;) ). My results are:
If you want to use an animation only on a part (AddMixingTransform) but you want to mix this partial animation with the base animation you have to:
If you have set your base animation to 0.33 and your partial to 0.66 the weights gets mixed as expected. On the rest of your model where only the base animation affects the bones will be a 100% weight since it get's normalized to 1.0 Thanks for the response! I suppose normalization would explain the 50% contribution. If the partial animation has 100% weight and the underlying animation has 100% weight, I guess you could do an add and normalize to produce 50% contribution each. But regular blending doesn't work that way--regular blending respects the layer as well. If this was not an additive blend, the animation on the higher layer would get its blend weighs first, take 100% control of those bones, and leave 0% remaining for the normalized result of subsequent animations. I guess that's why these are called "additive" animations, but it is hard to understand how the current implementation is useful. As for the deltas being "garbage," they should in fact be perfectly correct if the first frame of the animation is the bind pose. There might be some space inconsistency here--if bones are stored in world space rather than local space, or bone space, then you might not be able to trivially apply a delta from bind to create a pose. However the bones are stored, it seems like the skinned verts need a delta from bind to be oriented correctly in the end anyway. I guess what I'm after is an automated way to apply partial animations with normal blending rules to a model without having to manually specify which bones are animated. I guess additive animations are not this feature. In that case--what are they?
Jun 29 '11 at 11:01 PM
ChrisPruett
Well and additive animation applies the relative motion that is needed to transform the bones from the bindpose to the current frame. If you consider the additive animation to be the only one on that layer, so it's the only one that affects the selected bones, it would apply the relative motion of the current animation-time. In the next frame the bones are still in the last generated position and when you apply it again, the result will be moved two times the same relative amount which is not intended. Additive always needs another absolute animation which "resets" the bones each frame to be able to "add" some relative motion. Actually it seems that Unity don't even accepts an additive animation to be the only one on a layer. So it looks like it's ignoring the layer but i have to do some tests myself ;)
Jun 29 '11 at 11:49 PM
Bunny83
I see, I didn't consider bone accumulation. And yes, apparently the layer is ignored, which is unfortunate. I'll file a feature request for a proper bone overlay system; in the mean time I'm still interested in what additive animations are actually useful for. The only sample I've seen is the lean left and right sample, which seems to be easy to build with AddMixTransform().
Jun 30 '11 at 12:21 AM
ChrisPruett
I've added some details to my answer i've figured out ;) Well additive animations can be used for facial animations for example. The advantage is that even if some bones are animated (but no actual movement eg. always rotation == 0) it will not affect the bones because it just applies the relative motion / rotation. That way you can play 10 or more animations on the same bones but only the animated bones (with changes) get applied.
Jun 30 '11 at 01:20 AM
Bunny83
Thanks Bunny83. I went back and rewrote my system so that I can manually specify transforms to mix in the inspector. I am putting the partial animations on a higher layer than the base animations and letting normal blending rules apply, which works fine (e.g. I can cross fade my partial animations without affecting my base animations, etc). With respect to your 10 anims for facial movement example, it still seems like the requirement that animations are normalized will kill any usefulness from this feature. If you have 10 facial animations plus some base animation I assume each would automatically get a contribution of 10%, which is probably not what you want if you are implementing a blink or mouth movement or something similar. All of the animations will be averaged together and the result will be this blah average. What you want to be able to do in this case, I think, is control the blending weights so that you can, say, raise the eyebrows without affecting the appearance of the mouth. I guess if there is no overlapping in bone animation at all (and the base pose is also bind) you can control individual bones independently, but it still seems sort of useless. Maybe a better term is "extremely use-case specific." Anyway, thanks for the hints and research. I'll file a feature request for proper "overlay" animations. edit I added a feature request for an overlay animation pipeline. http://feedback.unity3d.com/forums/15792-unity/suggestions/1985253-proper-overlay-animation-support
Jun 30 '11 at 03:15 AM
ChrisPruett
(comments are locked)
|
