Animation Blending

I’m having trouble with animation blending. Here’s my code, explanation follows:

def AnimLoop(actor,toanim):
	actor.enableBlend()
	actor.play(actor.getCurrentAnim())
	actor.loop(toanim)
	Interv=LerpAnimInterval(actor, 0.5, actor.getCurrentAnim(), toanim)
	Interv.start()

What I want this function to do is blend an actor’s current animation into the animation given with the toanim parameter. It does work, almost. The problem is that the toanim animation does not end up being the only animation being played. In other words, if I wanted my actor to blend from walking to being idle, the walking animation does not completely stop looping. It looks as if it is being blended with the idle animation and both keep looping. If the character takes about 10 steps, which takes a few seconds, when walking, the walk animation does stop looping but does not completely stop having an effect on the idle animation. The actors legs are still apart.

Anyone have any ideas or maybe a better way to do this?

Edit| Just a better explanation…

You should probably check for a specific frame of the walk animation once you start blending to know when the walk should be completely idle…at which point you need to remove the walk animation from the “blender”. You could also control the weight of each animation, shifting the weight from walk to idle (last I checked, Panda handles this pretty well). I’m going to be doing alot of this myself later, but right now I dont have too much experience in the area. I’ll get back to you later when I’ve got a working method myself…

~silver~

The LerpAnimInterval is supposed to set the control effect of the original animation all the way to 0 after it’s finished. It doesn’t actually stop the animation, but it doesn’t need to: by setting its control effect to 0, it removes any visible contribution that animation will have on your actor.

Now, if you have some code somewhere that is setting its control effect to nonzero again, you might have a problem. If you can’t find the problem, try writing a very simple program that loads up your actor and plays the one LerpAnimInterval on it, then does nothing.

David

Oh, I should point out also that actor.getCurrentAnim() isn’t well-defined in the presence of blending. Which animation is the current one when you might have multiple animations playing?

I bet this is your problem. Note these two lines:

   actor.play(actor.getCurrentAnim())
   actor.loop(toanim) 

The first line is silly: it tells the actor to play its current anim (which is, by definition, the animation currently playing). So that line has no useful effect.
The second line tells the actor to start looping toanim. Since the actor is in blend mode, that means to add toanim to the list of animations currently playing. Now you do:

Interv=LerpAnimInterval(actor, 0.5, actor.getCurrentAnim(), toanim) 

Which creates a lerp from getCurrentAnim(), whatever that is, to toanim. If getCurrentAnim() returns the same thing as toanim (which it very well might, since that animation is now playing), then you are just creating a lerp from toanim to toanim–a do-nothing operation, and which has no effect on whatever animation was playing before you made this call in the first place.

Your best bet is to keep track of the “current” animation yourself. Failing that, call getCurrentAnim() only before you call enableBlend(), and store the result.

David

Thanks David.

This is what I ended up with:

def AnimLoop(actor,fromanim,toanim,rate=1,part=None):
	actor.enableBlend()
	actor.loop(toanim,partName=part)
	actor.setPlayRate(rate,toanim,partName=part)
	Interv=LerpAnimInterval(actor, 0.25, fromanim, toanim, partName=part)
	Interv.start()

I don’t need to change the duration, yet.