1 使用动画树状态机处理4方向动画的混合位置
创建动画树节点AnimationTree,绑定上节创建的动画节点

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

新建混合节点 BlendSpace2D ,用来管理休息动画,记得把混合模式改为虚线的
连续:每帧都更新属性。
离散:仅在位于关键帧时更新属性。
捕获:如果第一个关键帧的时间大于 0.0,就会记录该属性的当前值,并将其与第一个动画帧混合。例如,利用“捕获”模式,你可以将处于任意位置的节点移动到特定的位置。

中心点位置记得归零,同样的方法制作Run的混合位置,并和Idle节点、Start节点连接。
注意:Start的mode是Auto,动画直接是Enabled。

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轴

3 完成
