GD4 Using AnimationTree to Blend Animations
Asked Answered
E

9

0

*For Godot 4 Beta 1 Replace lerp() with lerpf()

Hi, Here is a quick beginner manual for using AnimationTree and use it to Blend between your animations. Warning I'm not much of a teacher 😅 Here I use GD4 but GD3 is pretty much the same.

You should already be familar with:
Godot User interface
Export/Import your 3D Model
AnimationPlayer
lerp()

First, using AnimationTree with "AnimationNodeStateMachine"

1. Add AnimationTree to your Player

2. In AnimationTree Panel:
-Choose AnimationNodeStateMachine as your Tree Root
-Assign your Player's AnimationPlayer
-Tick Active

3. Build your Animation StateMachine by:

3.1 To Add Animation
-Choose the first icon (The Arrow Pointer)
-Right Click empty area
-Add your Animations

3.2 To Link Animations
-Choose the 3rd icon
-Click to Drag and Link your Animations

3.3 To Blend Animation
-First select your Link
-Go to Properties and Increase "Xfade Time"

4. Code your Animation:
-By using the travel() and enter your animation's name, the AnimationTree's "playback" will travel to and play that animation. The Xfade Time you set will do the Blending for you. So just add the code to each input, for example.

	if Input.is_action_pressed("forward"):
		input.z += 1
		$AnimationTree["parameters/playback"].travel("walk")

4.1 I'm just showing the location of AnimationTree's "parameters/playback" that the code controls. Don't need to do anything.

PS There are other ways to code your animation, depends on how you set up your input for example. This is just quickest, easiest to show how it works.

If I made mistakes please let me know.

Equipoise answered 24/7, 2022 at 9:35 Comment(0)
E
0

AnimationTree: (AnimationNodeBlendSpace1D)

This set up is suitable for blending animations in a linear way. For example, if your Tree setup is idle <-> walk <-> run then your character will go from "idle" to "run" in that order (passing "walk" animation very quickly).

For my example, I will use walking "walkback" <-> "idle" <-> "walk".

You need to be familiar with set() and lerp().

Let's start

1. The set up is the same, just choose AnimationNodeBlendSpace1D as your Tree Root.

2. AnimationTree Graph area
At the bottom you will see the "value" 0 in the middle and "-1" on the left and "1" on the right. Basically you will place your animation within those value positions so animation "walkback" ,"idle" ,"walk" would be in the positions of -1 , 0 , 1

2.1 To place your animations:
-Use the 3rd Icon (dot with a pencil)
-Go to far left (-1) and Leftclick to add ("walkback") animation.
-Go to Middle (0) add ("idle").
-Go to far right (1) add ("walk").

Use the 1st icon and drag to see how your animation looks.
Use the 2nd icon (arrow pointer) to select your animation and move them.
Use Trash Icon to delete them if you need to.

3. Code your Animation

3.1 Playing animation when walking forward and backward.

-The parameters responsible for playing animation is "parameters/blend_position" and the value is between -1 to 1 (the same values you used to place your animation).
-Use set() to play that animation. Add the code to your forward input.

if Input.is_action_pressed("forward"):
	input.z += 1
	$AnimationTree.set("parameters/blend_position", 1)

This will play my forward "walk" animation because I place it on the (1) value in the Graph Area.
and

if Input.is_action_pressed("backward"):
	input.z -= 1
        $AnimationTree.set("parameters/blend_position", -1)

This will play my walking "walkback"
and

if velocity == Vector3.ZERO:
 	$AnimationTree.set("parameters/blend_position", 0)

This will play my "idle" when velocity = Vector3.ZERO (When I'm not pressing anything so my character has no movement).

3.2 To Blend your animations:
-You can blend it by replacing the value (-1,0,1) with lerp(). It will slowly increases/decrease to those value, therefore blending.

eg.

if Input.is_action_pressed("forward"):
	input.z += 1
	$AnimationTree.set("parameters/blend_position", lerp($AnimationTree.get("parameters/blend_position"),1,0.05))

This will slowly reach the value 1 (my "walk" animation).

$AnimationTree.set("parameters/blend_position", lerp($AnimationTree.get("parameters/blend_position"),-1,0.05))
This will slowly reach the value -1 (my "walkback" animation).

Equipoise answered 24/7, 2022 at 9:41 Comment(0)
E
0

AnimationTree: (AnimationNodeBlendSpace2D)

This set up is suitable for blending multiple animations.
You need to be familiar with set() and lerp().

Let's start

1. Set AnimationNodeBlendSpace2D as your Tree Root.

2. AnimationTree Graph area

You now have a Graph with X and Y values (each from -1 to 1).
You can place your animations anywhere on the graph area. Place your animations the same way you did with BlendSpace1D then code to play your animations by placing the Graph (x,y) values into the Code Vector2(x,y).

For example I place my "walk" animation at x = 0 y = 1 and "slideleft" at x=-1 y =0..and so on

3. Code your Animation

	if Input.is_action_pressed("forward"):
		input.z += 1
		$AnimationTree.set("parameters/blend_position", Vector2(0,1))

This will instantly play my "walk" animation because I placed it at x = 0 y = 1.

3.1 Blend Your Animation

Similar to BlendSpace1D but this time you will use lerp() to replace one or both of the Vector2(x,y) values so that it will reach that value slowly.
For example you can just declare that y = lerp(y, 1, 0.05) then plug it in Vector2 as (0,y):

if Input.is_action_pressed("forward"):
	input.z += 1
	y = lerp(y, 1, 0.05)
	$AnimationTree.set("parameters/blend_position", Vector2(0,y))

This means animation will instantly jump to value x = 0 but slowly reaching y = 1, which is where i placed my "walk" animation Vector2(0,1).

Or

if velocity == Vector3.ZERO:
	x = lerp(x, 0, 0.05)
	y = lerp(y, 0, 0.05)
	$AnimationTree.set("parameters/blend_position", Vector2(x,y))

This means animation will slowly reaching both x = 0 and y = 0, which is my "idle" animation.

Equipoise answered 24/7, 2022 at 9:43 Comment(0)
E
0

Combine/Nest Your AnimationTree Setups

You can combine/nest your AnimationTree setups and link them together (Useful when your character have many complex animations and you want to keep them organized).

You can choose any AnimationNode as a base setup for your Tree Root.

Example 1 Add BlendSpace1D to StateMachine Base

-For this I choose "AnimationNodeStateMachine" as Tree Root
-Then add "BlendSpace1D" and link it
-Then add more animations into that "BlendSpace1D". (eg. "walk slow" (-1), "walk normal"(0), "walk fast"(1))

Example walk forward input code:

if Input.is_action_pressed("forward"):
	input.z += 1
	$AnimationTree["parameters/playback"].travel("BlendSpace1D")
	$AnimationTree.set("parameters/BlendSpace1D/blend_position",-1)

First it tells AnimationTree to travel to BlendSpace1D Node, then tells BlendSpace1D Node to play the "walk slow" animation (-1).
You can also use lerp() in your BlendSpace1D animations.

Example 2 Add StateMachine to BlendSpace1D Base

You can combine/nest setups with any and as many AnimationNodes that are available, so try experiment with them.

Equipoise answered 28/7, 2022 at 16:16 Comment(0)
E
0

Mixing Your Animations

You can Mix your animations together by choosing only the bones of another animation to override the ones in your current animation. Just make sure the name of your bones are the same.

Here I have walking animation and an arm-pointing-forward (1 frame) animation (to give you icecream).

-I Choose AnimationNodeBlendTree as my Root Tree
-Add Blendspace2D for my walking animations
-Add arm-pointing-forward animation (icecream)
-Then I add Blend2 and connect them
-Choose Edit Filters and select the bones you want to override.
-In Blend2, try playing the "blend_amount" Slider (right under the number 0) to see how it blends.

Example Codes for input:

if Input.is_action_pressed("forward"):
	input.z += 1
	y = lerp(y, 1, 0.05)
	$AnimationTree.set("parameters/BlendSpace2D/blend_position", Vector2(0,y))

if Input.is_action_pressed("icecream"):
	$AnimationTree.set("parameters/Blend2/blend_amount", 1)
else:
	$AnimationTree.set("parameters/Blend2/blend_amount", 0)

When I press "forward" My character will do his walking animation, but when I also press "icecream" button his arm will raise up to give you icecream while walking.

You can use lerp() on the blend_amount number to make arm go into the pose smoothly.

Equipoise answered 28/7, 2022 at 16:26 Comment(0)
B
0

Hey is possible to use Blend for 2d animations?

Bouchier answered 4/8, 2022 at 16:52 Comment(0)
H
0

Bouchier AnimationTree should work for 2D as well, yes.

Hollister answered 4/8, 2022 at 22:9 Comment(0)
E
0

Just tested with Godot 4 Beta 1 and got lerp() errors:

Invalid call. Nonexistent utility function 'lerp'

and a bunch of :

E 0:00:00:0767   _disconnect: Attempt to disconnect a nonexistent connection from '<Animation#-9223372011772837472>'. Signal: 'tracks_changed', callable: 'AnimationPlayer::_animation_changed'.
  <C++ Error>    Condition "signal_is_valid" is true.
  <C++ Source>   core/object/object.cpp:1326 @ _disconnect()

If anyone has solution or better way of blending you can share them here, thanks

Equipoise answered 18/9, 2022 at 8:41 Comment(0)
R
0

Maybe you need lerpf() for stand alone values ?

Seems like lerp is implemented in multiple ways ...

Rooker answered 18/9, 2022 at 10:13 Comment(0)
E
0

Rooker Thank you. It's working again!

Equipoise answered 18/9, 2022 at 12:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.