1 使用动画树状态机处理4方向动画的混合位置

创建动画树节点AnimationTree,绑定上节创建的动画节点

屏幕截图 2024-05-31 130301

指定动画树结构,这里用状态机 AnimationNodeStateMachine

image-20240531130643190

新建混合节点 BlendSpace2D ,用来管理休息动画,记得把混合模式改为虚线的

连续:每帧都更新属性。

离散:仅在位于关键帧时更新属性。

捕获:如果第一个关键帧的时间大于 0.0,就会记录该属性的当前值,并将其与第一个动画帧混合。例如,利用“捕获”模式,你可以将处于任意位置的节点移动到特定的位置。

image-20240531133635442

中心点位置记得归零,同样的方法制作Run的混合位置,并和Idle节点、Start节点连接。

注意:Start的mode是Auto,动画直接是Enabled。

image-20240531215504987

2 更新Play脚本控制动画播放

  • 访问动画树
1
@onready var animation_tree: AnimationTree = $AnimationTree
  • 混合位置同步移动位置
1
2
animation_tree.set("parameters/Idle/blend_position",input_vector)
animation_tree.set("parameters/Run/blend_position",input_vector)
  • 获取状态机的播放控制
1
@onready var animationState =animation_tree.get("parameters/playback")
  • 使用travle()方法播放动画,travel():按照最短的路径从当前状态过渡到另一个状态。
1
animationState.travel("Run")

休息动画也是一样的做法,不赘述

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
extends CharacterBody2D

const ACCELERATION = 15 * 60
const MAX_SPEED = 100
const FRICTION = 10 * 60

var input_vector = Vector2.ZERO

@onready var animation_player: AnimationPlayer = $AnimationPlayer
@onready var animation_tree: AnimationTree = $AnimationTree
@onready var animationState =animation_tree.get("parameters/playback")

func _physics_process(delta: float) -> void:

# 更新输入向量(仅当输入发生变化时才重新计算归一化)
input_vector.x=Input.get_axis("ui_left", "ui_right")
input_vector.y=Input.get_axis("ui_up", "ui_down")
if input_vector.length() > 0.01: # 防止除以零
input_vector = input_vector.normalized()

#非零向量
if input_vector != Vector2.ZERO:

#if input_vector.x >0:
#animation_player.play("RunRight")
#else :
#animation_player.play("RunLeft")
animation_tree.set("parameters/Idle/blend_position",input_vector)
animation_tree.set("parameters/Run/blend_position",input_vector)
animationState.travel("Run")

velocity = velocity.move_toward(input_vector * MAX_SPEED,ACCELERATION * delta - FRICTION * delta)
else :
animationState.travel("Idle")
#animation_player.play("IdleRight")
velocity = velocity.move_toward(Vector2.ZERO,FRICTION * delta) #摩擦力

move_and_slide()
  • 设置斜角移动优先级

为了使左右动画更优先播放,可以把y轴设置得更长,这样45°时,更偏向x轴

image-20240531223610622

3 完成

动画