Baste-RainGames / AnimationPlayer

An animation player for Unity, to replace the Animator/AnimatorController.
MIT License
89 stars 7 forks source link

Recommended way to do a Jump animation #2

Closed davidseth closed 5 years ago

davidseth commented 6 years ago

@Baste-RainGames I can see you updated your code with Events. Nice.

Using your AnimationPlayer framework, what would your recommended pattern be for a jump type animation?

So my character controller calls PlayerJump() when the "Jump" button is pressed. What would I do with my Idle/Walk/Run BlendTree1D that I have? Would I create a new layer with a Jump animation, transitioning to it and then back to the bottom layer with the BlendTree1D?

I'm just trying to wrap my head around Playables API and especially your great framework.

BTW, I exposed layerMixer in AnimationLayer.cs as a public variable

public AnimationLayerMixerPlayable LayerMixer

on line 23 and in 113 by adding it:

LayerMixer = layerMixer;

This way I have an easy way to call the SetinputWeight method on the Layer like:

layers[0].LayerMixer.SetInputWeight(0, LayerOneWeight);

layers[1].LayerMixer.SetInputWeight(1, LayerOneWeight);

This allow me to quickly blend the layers in real time in the Unity editor by adding some public [Range(0, 1)] variables for LayerOneWeight & LayerOneWeight.

Baste-RainGames commented 6 years ago

The idea would just be to have a Jump state that you Play, and then when it's done, Play the blend tree again.

So right now I do things like that by:

StartCoroutine(Jump());

...

IEnumerator Jump() {
    animationPlayer.Play("Jump");
    var timeBeforeBlendOut = animationPlayer.GetCurrentPlayingState().Duration * 0.8f;
    yield return new WaitForSeconds(timeBeforeBlendOut);
    animationPlayer.Play("Movement");
}

That assumes that the blend tree you want to return to is named Movement. This is where I often would use PlayDefaultStateIfPlaying (which I think is new in the latest commit) - ie. PlayDefaultStateIfPlaying("Jump"). So if the game has some reason for not wanting to transition back into Movement (eg. a ledge grab or whatever), you don't have to check for that.

With the chaining from the other issue, it would be more like:

animationPlayer.Play("Jump");
animationPlayer.PlayAfterFraction(.8f, "Movement")

Which allows skipping the coroutine, and looks ok.

On the layers thing - I didn't realize that I hadn't added any way to update the weight of layers. I'll add that to the list of things to do.

davidseth commented 6 years ago

Thanks for the explanation and the code. Very helpful.

For your jump animation, are you using 2 or 3 animations in sequence (ex: JumpUp, JumpMid, JumpFall) or just one animation? I ask as again I'm wondering how you are handling these things in the Playables system. In Mecanim this would be a sub-state machine but of course that is not available in Playables.

Baste-RainGames commented 6 years ago

Ah, animation sequences.

I'm not doing anything like that in the project I'm working on. In my todo list, I have an entry for making sequences, which is essentially a string together of different animations.

So, assuming that the duration of the jump varies (based on how far you fall, the setup I want to enable with sequences is:

1) when you start jumping, you play the "Jump" animation. The jump animation is a sequence, which is set up to first play JumpUp, and then loop JumpMid. 2) When you need to land, you play the JumpLand animation, and queue a return to movement.

An alternative way I've thought about doing this is something I call "Transition by clip". In essence, you'd be able to say "Play JumpMid, but transition through JumpUp first", or "Play Movement, but transition through JumpLand first". I'm not quite sure how that'd look, though.

For now, you'd have to do those things manually - play JumpUp, wait, then play JumpMid, then wait, then play JumpLand, then wait, then play Movement. Not ideal!