jmonkeyengine icon indicating copy to clipboard operation
jmonkeyengine copied to clipboard

Animation: BlendAction does not honor speed

Open MeFisto94 opened this issue 4 years ago • 7 comments

I have to give this a check, chances are I am doing things wrong or there is some documentation about this already, this issue is more of a reminder to me, but:

composer.action("Run").setSpeed(4f);
System.out.println(composer.action("Run").getSpeed()); // 4

BlendAction action = composer.actionBlended("Walking, Running", new LinearBlendSpace(1, 4), "Walk", "Run");
action.getBlendSpace().setValue(4f);

//composer.setCurrentAction("Walking, Running");
composer.setCurrentAction("Run");

This sets the speed of the Running Animation to 4. If the BlendAction is used, the Running Animation clearly isn't up to speed.

Edit: I already found something: actionBlended calls "makeAction" instead of action, so it does not use the "cached" action for Run but creates a fresh one from the AnimClips. Personally I have an odd feeling about using Strings as keys and the Controls being giant hash maps, specifically if all the methods return Actions.

It feels like I am supposed to pass them and keep multiple almost identical Actions, but this only works in some scenarios, depending on what the Control has in it's HashMap.

The problem is we probably cannot/shouldn't refactor the whole code, specifically as the old animation system was designed the same way.

MeFisto94 avatar Feb 27 '20 23:02 MeFisto94

Edit: I already found something: actionBlended calls "makeAction" instead of action, so it does not use the "cached" action for Run but creates a fresh one from the AnimClips.

Doing so won't make any difference I guess. You can not set speed individually on each child of BlendAction. That's because AnimComposer reads the speed only from the parent action ("Walking, Running" action in your case) to update the action.

And, note that blending multiple actions using BlendAction will stretch all of them to the max length. For example, say "Walk" action is 3s and "Run" action is 2s. If you blend them using BlendAction the "Run" action will be stretched to 3s.

I guess what you can do is that you can sync the speed of "Walking, Running" action by a factor of character movement speed like you are doing for blend value.

Ali-RS avatar Feb 28 '20 06:02 Ali-RS

You are right: https://github.com/jMonkeyEngine/jmonkeyengine/blob/0fd70b81c93adde86a3590db49725a0c68fc3618/jme3-core/src/main/java/com/jme3/anim/tween/action/BlendAction.java#L39-L40

And no, I have a problem with that: Run is 1 second, Walk 3 or 4 seconds (there could be other more extreme examples) and no matter how I scale it, I get a relativly long stretched run animation that way.

Can you imagine what artifacts it could cause when not having animations of the same length? I mean I think about changing this so that the animation is just looping, that way the speed would be hornored and a shorter animation is looped.

Maybe we need to make it toggleable, because some animation would look bad when looped, maybe having Mode.Loop, Mode.StretchShorter and Mode.CutLonger

MeFisto94 avatar Feb 29 '20 19:02 MeFisto94

Can you imagine what artifacts it could cause when not having animations of the same length? I mean I think about changing this so that the animation is just looping, that way the speed would be hornored and a shorter animation is looped.

Don't know, we should try and see what will happen ;) And yeah, it seems to be a nice idea to add a loop mode in addition to stretching.

Ali-RS avatar Mar 01 '20 05:03 Ali-RS

While I like the option of having looping in this scenario. But given that you could have a 1 second animation for start walking, then transition into a 3 second animation for walking, both looping and stretching would look bad.

tlf30 avatar Mar 13 '20 04:03 tlf30

Well in that case you would have those animations as a sequence though and you don't really blend between them.

In practice you would have sequence(StartWalk, blend(Walk, Run, 0.5f)) and then just control the second action.

This evening I might paste in an example I did to show off the new animation system where this issue is visible (Jaime's Run Animation is way shorter than the Walk animation, leading to a moonwalk feeling)

MeFisto94 avatar Mar 13 '20 12:03 MeFisto94

Edit: I already found something: actionBlended calls "makeAction" instead of action, so it does not use the "cached" action for Run but creates a fresh one from the AnimClips.

Yes that's true , but i think you can bypass this using :

        //8)Create ClipAction instances for the AnimClips (BlendableActions)
        ClipAction capRotationClip=new ClipAction(capRotationAnimClip);
        ClipAction bottleTractionClip=new ClipAction(bottleTractionAnimClip);
        capRotationClip.setTransitionLength(200d);
        bottleTractionClip.setTransitionLength(150d);
        //9)feed the BlendableActions to a single BlendAction
        BlendAction blendAction=new BlendAction(this,bottleTractionClip,capRotationClip);
        //10)add that BlendAction to the AnimComposer using addAction(...)
        animComposer.addAction("SimulateBottleFall",blendAction);
        animComposer.getAction("SimulateBottleFall").setSpeed(4f);//or use blendAction.setSpeed(4f);
        //11)run this BlendAction in the default layer
        animComposer.setCurrentAction("SimulateBottleFall");    

So, there are multiple ways to do it & this is code is the same code that actionBlended uses but instead of creating inaccessible instances using actionBlended , you can do it into your code then add the result BlendAction to the ActionMaps of the AnimComposer.

& yes , when i do this too : bottleTractionClip.setSpeed(200f); for the bottleTractionClip then feed that clip into the blendAction , it gets ignored .

pavly-gerges avatar Apr 07 '21 14:04 pavly-gerges

And yeah, it seems to be a nice idea to add a loop mode in addition to stretching.

Experimenting with the loop mode in BlendAction

https://github.com/Ali-RS/jmonkeyengine/compare/master...Ali-RS:fix-blend-action

Example Videos: https://hub.jmonkeyengine.org/t/a-tip-for-animation-blending/44617/7?u=ali_rs

Feedbacks?

Ali-RS avatar May 20 '21 09:05 Ali-RS

Fixed in https://github.com/jMonkeyEngine/jmonkeyengine/pull/1848

BlendAction automatically generates a speed factor for each child to resolve the slow-motion effect. One can still adjust the factors to his own desire.

Ali-RS avatar Aug 28 '22 06:08 Ali-RS