Animation Manager ?

Started by
7 comments, last by xerzi 9 years, 7 months ago

Well right now just thinking about doing animations just seems like a giant cliff i need to scale. I've read about some patterns commonly used for animation. Well i am trying to rework an animation system that's already been done without altering too much.

There are 3 types of animations:

Static - basically whole raw animation, every bone is set with the animation.

Overwrite - only some animation data is decoded and overwrites existing frame data.

Additive - contains basically the "change" information that modifies the existing frame data.

As an example, for a 3d character. "Static" would be something like a running animation. Overwrite would be something like a melee (so you can run and hit something at the same time). Additive would be aiming, the rotation of the head and arms to modify depending on where you are aiming.

So now there are some conflict as when a melee animation is happening, then there shouldn't be any aiming, otherwise it would distort the melee animation.

I know i've read about state machines but i can't wrap my head around some ideas. If someone maybe knows of a demo program, that has a character animation with several animations and different states of the character going from and into? A lot of the examples I see are relatively simple and i find they don't really demonstrate enough to get a good idea.

Thanks for any help.

Advertisement

First: I'm not aware of any demo programs that illustrate or implement the type of animations in combination you mention.

Second:


i am trying to rework an animation system that's already been done without altering too much.

As it appears you already have the bases for the 3 types of animation in place, can you be a little more specific about what you want to change, what (if any) problems you've encountered?

Assuming you're talking about skinned mesh animation (you don't mention what type of animation system you have): with regard to combining animations, perhaps this article on a blending animation controller will help.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.


As an example, for a 3d character. "Static" would be something like a running animation. Overwrite would be something like a melee (so you can run and hit something at the same time). Additive would be aiming, the rotation of the head and arms to modify depending on where you are aiming.

So now there are some conflict as when a melee animation is happening, then there shouldn't be any aiming, otherwise it would distort the melee animation.

I know i've read about state machines but i can't wrap my head around some ideas. ...

Look for the keywords

* animation blending: mixing animations on the same parts using weights,

* animation layering: overriding animations or suppressing them,

* animation masking: applying an animation only to the parts that are marked (e.g. specific body parts of a skeleton).

A state machine is useful to select animations, but its isn't useful for the mentioned purposes. The construct to control above mechanisms is often called animation tree or blend tree.

@Buckeye

The demo doesn't have to be specific to my implementation, i just want to be able to see a demo of something more complex than one or two animations.

Well the code handling it right now is a bit of a mess, can't really say it's better than spaghetti code. That combining animation is pretty neat, thanks for the read. The blending i need to do doesn't need to happen over time though. It is calculated biased on aim direction, and if it needs smoothing that can be done by adding a rate of change to the aim direction so it doesn't just snap in place. Which needs to be blended between 4 frames anyway usually (left-right, up-down), idk if a controller is really necessary there. It's more how to manage and when to play specific animations. So when i aim playing a melee, reload or gesture animation, i shouldn't be blending in the rotation animation (as that is only relevant when idle, running, or firing).

@haegarr

So as an example, i choose the animation "running melee" and then i go to the blend tree which defines "running melee" as the two animations "running" and "melee" and mixes them (or in my case overwrites the needed nodes with the melee animation)? I might be getting that wrong, but how would the blend tree know then which frame the running is on and which frame the melee is on? Maybe that's a bad example on my part...

So as an example, i choose the animation "running melee" and then i go to the blend tree which defines "running melee" as the two animations "running" and "melee" and mixes them (or in my case overwrites the needed nodes with the melee animation)? I might be getting that wrong, but how would the blend tree know then which frame the running is on and which frame the melee is on? Maybe that's a bad example on my part...

Let us say there are the animations idleStand, moveWalk, moveRun, leanLeft, leanRight, meleeAttack.

The first thing to do is to use a variable forwardSpeed to mix the animations idleStand, moveWalk, moveRun by blending so that e.g. for a speed greater or equal 0 and lesser than 3 the animations idleStand and moveWalk, and for a speed greater or equal 3 and lesser then 6 (the maximum speed) the animations moveWalk and moveRun are blended. The blend weights are then computed e.g. like so:

w_idleStand = ( forwardSpeed < 3 ) ? ( 1 - forwardSpeed / 3 ) : ( 0 )

w_moveWalk = ( forwardSpeed < 3 ) ? ( forwardSpeed / 3 ) : ( 1 - ( forwardSpeed - 3 ) / 3 )

w_moveRun = ( forwardSpeed < 3 ) ? ( 0 ) : ( ( forwardSpeed - 3 ) / 3 )

This would be the job of the "move forward" branch of the animation tree.

The next would be to use a variable lean to mix the result from above with either leanLeft or leanRight. It may be implemented as an additive animation, or perhaps also by linear blending with appropriate weights.

With the above set-up the entire skeleton is animated (e.g. also the upper body and the arms are animated accordingly). Now when the meleeAttack animation comes into play, it should override what the above animation defines for upper body and arms. This is done by defining a new layer for meleeAttack. This layer works on the upper body and the arms only, not on the legs. One possibility to implement the layering is to give each part (or perhaps each bone) and contingent of 100%. If a layer write animation data to a part / bone, then the contingent is reduced by a defined amount. Any layer below is allowed to mix in as much as the remaining contingent says.

An example: At the beginning of computing the pose, the contingent is initialized with 100%. The top layer with the meleeAttack is not playing, so the contingent is not reduced. The lower layer where the forward movement is handled has 100% control over the entire body. Later on the meleeAttack is triggered. The upper layer takes control of the parts upper body and arms, sets them into an appropriate pose, and reduced the contingent by, say, 95%. So the lower layer with the forward movement is able to influence the upper body and arms with just 5%. For a total override a layer would reduce the contingent by 100%, of course.

Seen as an animation tree, we have 3 leaf nodes with the animations idleStand, moveWalk, and moveRun. These 3 nodes are the leafs of a one axis linear blend node. The output of that blend node is forward movement. Further we have 3 leaf nodes for the animations leanLeft, leanRight, and Identity. These nodes are the leafs of a blend node which effectively selects one if its children. Both the forward movement and leaning nodes are children of an additive blend node. Further we have a leaf node with meleeAttack. Both the output of the additive blend node and the meleeAttack node are children of a layering node parametrized as described above.

As can be seen from this description, animations are not directly chosen. Instead, the animation parameters are set accordingly to the situation. E.g. the forwardSpeed variable is set to 1.5, the leaning variable to -0.25, and the attack variable to true. These settings are driven from the player controller in the case of the PC or from the animation controller in case of an NPC.

EDIT: BTW, all this does not mean that a state machine cannot be useful. Just notice that a state machine is good for discrete distinctions (the states), while the mechanisms described above easily allow for continuos mixing.

Ok so this is where that all makes sense from an abstract stand point, but i get confused about some implementation details.

For forward movement, how is the frame determined for all of the animations? Is there an animation frame index for each of the 3 at once, or are they expected to all be the same length and match. So at frame 5 the right leg is up in walk and the right leg is also up in the run animation. Otherwise the blending wouldn't work?

For the meleeAttack, when the condition is false it does 2 things, 1) it doesn't blend anything into the animation 2) it sets the frame index to -1, so when the condition becomes true and the frame is incremented it'll be "0"?

So rather than using a state machine to manage the animation, it'd be possible to use a state machine to manage the objects state. So if i am in a state "climbing wall", that state would make sure meleeAttack's condition is set to false as you can't melee while climbing a wall?

How about transitional blending? So say i am "moving forward" and then i go into a "climb wall" i would want to blend the current walking forward animation into the start of a climbing wall animation so that there isn't any kind of stutter. This would then require a state machine correct? To know when we are in one state, and want to go to another to trigger a blending operation between the two states? I don't think the blend tree would work here though, as forward movement would go to zero when climbing, but i'd want to blend the animation that was happening when the climb state was trigger (i assume just copy the node data and blend from 0 to 1 from the old node data to what the actual animation is) but then i can also choose to not blend certain state changes?

The details need attention, as always, and there are often more than a single way to do things.


For forward movement, how is the frame determined for all of the animations? Is there an animation frame index for each of the 3 at once, or are they expected to all be the same length and match. So at frame 5 the right leg is up in walk and the right leg is also up in the run animation. Otherwise the blending wouldn't work?

Let the moveWalk animation have a length of 2 seconds for a single cycle. After this 2 seconds the animation loops and hence starts at the beginning. If forwardSpeed has the value of 3, the animation is played at nominal speed, i.e. one cycle in 2 * 3 / 3 = 2 seconds. If forwardSpeed is 1.5 (the half value), then the full cycle of the animation need to be played in 2 * 3 / 1.5 = 4 seconds (the double value). If forwardSpeed has the value of 4.5, the full cycle lasts 2 * 3 / 4.5 = 1.33 seconds. This means that the animation is played back with an adapted speed.

The same is true for the moveRun animation, but here the duration of a cycle is, say, 1 second. Again, this duration is defined for the nominal forwardSpeed of 6. So, when forwardSpeed is 4.5, the full cycle just lasts for 1 * 6 / 4.5 = 1.33 seconds which is, not by accident, the same duration of a full cycle of moveWalk when forwardSpeed is 4.5.

Fine so far, but not enough to make the animation look good when moveWalk and moveRun are blended. It is also required that the both animation run in the same motion phase. E.g. both animations have the left foot on the ground at the beginning and at the end of the cycle, and both have the right foot on the ground in the middle of the cycle. In other words, both animations are in the same motion phase for a given percentage of the cycle.

How keyframes are distributed over a cycle is not important in this sense. Both the cycles of moveWalk and moveRun may have a different count and/or spacing of keyframes. The distribution of keyframes depends only on the question of motion quality. Thing is, you need to use the accordingly adapted animation time.


For the meleeAttack, when the condition is false it does 2 things, 1) it doesn't blend anything into the animation 2) it sets the frame index to -1, so when the condition becomes true and the frame is incremented it'll be "0"?

1) Yes, the meleeAttack is needed to be suppressed.

2) When the animation is triggered, its local playback time can be reset, so ever staring at 0.


So rather than using a state machine to manage the animation, it'd be possible to use a state machine to manage the objects state. So if i am in a state "climbing wall", that state would make sure meleeAttack's condition is set to false as you can't melee while climbing a wall?

It is okay to combine all this with a state machine, where blend trees are embedded in nodes. For example, "normal" and "climbing" are states, where the state "climbing" may be entered only if forwardSpeed is 0, so that the "normal" state would show idleStand.


How about transitional blending? So say i am "moving forward" and then i go into a "climb wall" i would want to blend the current walking forward animation into the start of a climbing wall animation so that there isn't any kind of stutter.

That's what the article I referenced was about. With an animation controller, you would play 2 animations on separate tracks and add them together with a blend factor which varies with time. That is, to change from animation1 to animation2, you would render each frame with (pseudo-formula) animation1 * factor + animation2 * (1 - factor). The factor variable is setup to range from 1 to 0 in x seconds, where x is the length of time you choose to make the transition.

Syncing the animations for the case you mention would likely be better with walk->prepareToClimb, then prepareToClimb->climb - where prepareToClimb is an idle pose, perhaps with arms extending upwards a bit, and which matches the beginning of the climb animation. You have to plan a bit because transitioning from a horizontal move (walking) to a vertical (climbing) might look a bit awkward as the character slowly walks off the ground, rises at an angle with arms beginning to grab, and miraculously attaches to the wall moving upward. huh.png

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

Alright i think i have a better understanding of how it'll work now, thanks for all the help!

This topic is closed to new replies.

Advertisement