HOME / 第 4 部分 · UI 界面 · 动画 · 特效 / 第 41 课
MODULE 4 · UI 界面 · 动画 · 特效

第 41 课 · AnimationTree 动画状态机

⏱ 预计时长 35 分钟📊 难度 进阶📚 模块 第 4 部分 · UI 界面 · 动画 · 特效

🎯 本课学习目标

角色动画多了以后,用状态机统一管理最清晰。本课用 AnimationTree 做「待机/走路/跳跃」自动切换。

📖 详细教学步骤

为什么要用动画状态机?概念

角色有 idle(待机)、walk(走路)、jump(跳跃)等多个动画,用 if-else 手动播放会越来越乱。状态机用「状态 + 条件」自动切换:

  • 在地面 + 移动 → walk
  • 在地面 + 不移动 → idle
  • 不在地面 → jump

先准备动画搭建

用第 39 课的方法,在 AnimationPlayer 里创建:

  • idle:待机动画(循环)
  • walk:走路动画(循环)
  • jump:跳跃动画(不循环)

添加 AnimationTree搭建

  1. 添加子节点 AnimationTree
  2. 检查器:Tree Root → 新建 AnimationNodeStateMachine
  3. Anim Player → 选择 AnimationPlayer
  4. 勾选 Active(激活,交给状态机管理播放)

在状态机里添加状态操作

  1. 双击 AnimationTree 打开「动画树」面板
  2. 在「状态机」空白处右键 → 添加动画(Add Animation)→ 选 idle
  3. 同样添加 walk 和 jump 三个状态节点
  4. 从 idle 拖一条连线到 walk,walk 到 idle 等,建立转换
  5. 点击连线,设置转换条件(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 做平滑过渡。