HOME / 第 4 部分 · UI 界面 · 动画 · 特效 / 第 41 课
MODULE 4 · UI 界面 · 动画 · 特效
第 41 课 · AnimationTree 动画状态机
🎯 本课学习目标
- 理解动画状态机的思想
- 用 AnimationTree 管理多个动画
- 实现 idle/walk/run/jump 状态切换
角色动画多了以后,用状态机统一管理最清晰。本课用 AnimationTree 做「待机/走路/跳跃」自动切换。
📖 详细教学步骤
为什么要用动画状态机?概念
角色有 idle(待机)、walk(走路)、jump(跳跃)等多个动画,用 if-else 手动播放会越来越乱。状态机用「状态 + 条件」自动切换:
- 在地面 + 移动 → walk
- 在地面 + 不移动 → idle
- 不在地面 → jump
先准备动画搭建
用第 39 课的方法,在 AnimationPlayer 里创建:
- idle:待机动画(循环)
- walk:走路动画(循环)
- jump:跳跃动画(不循环)
添加 AnimationTree搭建
- 添加子节点
AnimationTree - 检查器:Tree Root → 新建
AnimationNodeStateMachine - Anim Player → 选择 AnimationPlayer
- 勾选 Active(激活,交给状态机管理播放)
在状态机里添加状态操作
- 双击 AnimationTree 打开「动画树」面板
- 在「状态机」空白处右键 → 添加动画(Add Animation)→ 选 idle
- 同样添加 walk 和 jump 三个状态节点
- 从 idle 拖一条连线到 walk,walk 到 idle 等,建立转换
- 点击连线,设置转换条件(Transition)
设置转换条件(代码控制)代码
转换条件由脚本里的参数驱动:
GDSCRIPTextends CharacterBody2D
@onready var anim_tree: AnimationTree = $AnimationTree
@onready var anim_state = anim_tree.get("parameters/playback")
func _physics_process(delta):
var moving = abs(Input.get_axis("move_left", "move_right")) > 0.1
# 设置状态机参数
anim_tree.set("parameters/conditions/is_moving", moving)
anim_tree.set("parameters/conditions/is_falling", not is_on_floor())
# 或直接播放
if not is_on_floor():
anim_state.travel("jump")
elif moving:
anim_state.travel("walk")
else:
anim_state.travel("idle")
状态机转换的过渡时长操作
双击转换连线,设置:
- Switch Mode:At End(当前动画播完再切)或 Immediate(立即切)
- Xfade Time:交叉淡入淡出时间(如 0.2,过渡更顺滑)
💡 走路↔待机用 0.2 淡入,跳跃用 Immediate。
⚠️
动画树没反应?
确认:①AnimationTree 的 Active 已勾选;②Anim Player 已指定;③Tree Root 是状态机;④travel 的动画名与状态节点名一致。
⚠️
状态切不过去?
检查转换连线是否从正确状态出发、条件参数名是否与 set 的一致。
🧪 动手试一试
🏋️ 课后练习
用 AnimationTree 做 idle/walk/jump 三状态:地面移动切 walk、静止切 idle、离地切 jump,并加 0.2 过渡。
三个动画 + 状态机连线 + 代码 travel/参数控制。
💡
状态机用参数(conditions)驱动比代码直接 travel 更灵活,也支持动画树编辑器可视化调试。
💡
角色动画复杂后,状态机是唯一清晰的方案。
🎓 本课小结
AnimationTree + 状态机统一管理多动画:状态节点 + 转换连线 + 条件参数;travel() 切换、Xfade 做平滑过渡。