资讯动态

Godot 2D骨骼动画实战:用AnimationTree状态机搭出5个流畅角色状态

发布时间:2026/9/18 13:38:26 来源:尧图企业网站定制
Godot 2D骨骼动画实战用AnimationTree状态机搭出5个流畅角色状态【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址: https://gitcode.com/GitHub_Trending/go/godot-demo-projects跑动中按下跳跃键角色腾空的一帧里腿还保持着跑步姿势落地时又生硬地顿了一拍——这类2D骨骼动画的卡顿多数不是动画本身画得差而是动画状态没有和物理状态同步切换。本文直接拆 Godot 官方演示项目里的 2d/skeleton/ 示例一个用 Skeleton2D 绑定的小机器人 gBot配了 8 段动画、5 个可切换状态代码量不到 100 行但把骨骼 动画库 状态机这条完整链路都走了一遍。一图看懂三层结构各管一件事先建立全局印象。整个角色系统分三层每层只干一件事骨骼层Sprite2D下的Skeleton2D挂了一棵Bone2D树Hip → Chest → Head/Chin双臂三节、双腿三节身体部件是若干Polygon2D靠skeleton属性和bones权重绑定到骨骼上骨骼转动时多边形跟着形变。动画层AnimationPlayer里放了一个 AnimationLibrary动画的素材库资源存了 8 段动画idle、walk、run、fly、fall、jump、land、land_hard。每段动画本质就是各骨骼rotation_degrees和Hip:position的关键帧。状态层AnimationTree可以理解为动画的路由表决定此刻播放哪段动画、如何过渡通过一棵 BlendTree 把上面两层接起来。注意这个图里藏着一个关键设计jump、land、land_hard不是状态而是OneShot一次性播放链在 Transition 节点后面。跳跃动作播完后自动交回状态机不会把跑步动画卡断。动手搭建跟着demo一步步接上第1步先搭骨骼再画动画打开 player.tscn角色根节点是CharacterBody2D。骨骼层级按运动学来分Chest带动HeadHip带动两条腿——父骨骼一转子骨骼跟着走这样每段动画只需要关键帧少数几根骨骼。为什么这么分看run动画就知道它只给Hip、LeftLeg、RightLeg、Chest、双臂记了关键帧Chin、RightHand这些节点的关键帧全是 0靠父骨骼的转动自然带出跟随效果。骨骼数压下来动画制作成本和运行时开销一起降。第2步8段动画进同一个AnimationLibrary演示把全部动画存在AnimationPlayer的一个 AnimationLibrary 资源里。做自己的项目时同理待机、走、跑、飞、落、跳、轻落地、重落地各一段命名和后面的状态名保持一字不差。第3步搭BlendTree把状态和一次性动作分开在 AnimationTree 编辑器里做三件事加一个AnimationNodeTransition作为状态容器5 个输入口依次接 idle / walk / run / fly / fallxfade_time设 0.1 秒——这就是状态之间那 0.1 秒的平滑交叉淡化。给 walk 和 run 各串一个AnimationNodeTimeScale节点后面用脚本调播放速度。把 jump、land、land_hard 三个AnimationNodeOneShot依次链在 Transition 之后sync都设为 true同步播放避免和状态动画打架。然后在脚本里打开开关漏了这一步整个树都是哑巴func _ready() - void: # 必须手动激活否则AnimationTree什么都不播 $AnimationTree.active true第4步用物理状态驱动路由核心逻辑全在 player.gd 的_physics_process里先跑物理再根据结果点名该播哪个状态。注意顺序——一定在move_and_slide()之后读is_on_floor()和velocity读早了一帧动画就会慢一拍if is_on_floor(): if abs(velocity.x) 50: # 按水平速度点名状态顺带把跑动速度写进TimeScale $AnimationTree[parameters/state/transition_request] States.RUN $AnimationTree[parameters/run_timescale/scale] abs(velocity.x) / 60 elif velocity.x: $AnimationTree[parameters/state/transition_request] States.WALK else: $AnimationTree[parameters/state/transition_request] States.IDLE else: # 空中按垂直速度方向区分上抛和下落 $AnimationTree[parameters/state/transition_request] \ States.FALL if velocity.y 0 else States.FLYtransition_request是 Transition 节点暴露的参数写入状态名它就自动在 0.1 秒内交叉淡化过去。速度阈值 50 把走和跑分开/ 60是个经验除数让动画周期和位移节奏大致匹配脚步不打滑。第5步落地分级 跳跃手感跳起瞬间触发 jump OneShot落地时按垂直速度分两档——falling_fast达到TERMINAL_VELOCITY400播land_hard并锁 0.4 秒水平移动做出硬直falling_slow则播普通的landif is_jumping: $AnimationTree[parameters/jump/request] AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE if falling_fast: # 重落地播一次性动画并冻结0.4秒横向移动 $AnimationTree[parameters/land_hard/request] AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE no_move_horizontal_time 0.4 elif falling_slow: $AnimationTree[parameters/land/request] AnimationNodeOneShot.ONE_SHOT_REQUEST_FIRE另外两处小手感值得抄提前松开跳跃键时velocity.y * 0.6短跳更跟手左右移动时把Sprite2D.scale.x翻正负号角色自动转身。进阶技巧 TimeScale让跑动速度真起来静态动画里 6px/帧 和 30px/帧 看起来一样快脚就拖地了。demo 把abs(velocity.x) / 60持续写进parameters/run_timescale/scale跑得越快动画越快。走、跑各挂一个 TimeScale 就够了不用拆两套动画。 用调试器盯 current_state 定位状态漂移动画和你预期不一致时先确认树实际停在哪# 随时打印当前状态名看它和物理状态是否对得上 print($AnimationTree[parameters/state/current_state])打印值和is_on_floor()、velocity.x对比基本能定位是阈值问题还是分支漏写。 状态变多时升级到代码级状态机动画层的状态机管播什么管不了能被打断什么。加攻击、眩晕这类可中断状态时看 2d/finite_state_machine/它的 player_state_machine.gd 用states_stack栈保存被覆盖的状态动作结束切回previous就自动还原连跑步中起跳要把速度带进空中这种细节都有对应处理if state_name PLAYER_STATE.jump and current_state move: # 把地面的速度传递给跳跃状态落地后继续跑而不是原地刹住 jump.initialize(move.speed, move.velocity)踩坑清单现象原因解法跑步时脚拖地、像踩轮滑动画播放速度与位移脱钩run/walk 前串AnimationNodeTimeScale脚本每帧写parameters/run_timescale/scale跳跃动作被跑步动画截断把 jump 做成了 Transition 的普通状态jump/land 改用AnimationNodeOneShot挂在状态机后面代码发ONE_SHOT_REQUEST_FIRE跳起来后一直在空中跑步_physics_process里漏了not is_on_floor()分支空中按velocity.y正负切fly/fall重落地后角色没顿住只播了动画没锁物理像 demo 一样设no_move_horizontal_time 0.4期间强制velocity.x 0低帧率下角色抖动、穿墙渲染帧和物理帧不同步根节点开physics_interpolation_mode 1demo 的 CharacterBody2D 已默认开启延伸阅读2d/finite_state_machine/代码级层级状态机完整实现带攻击/眩晕等可中断状态和可视化调试面板适合从 AnimationTree 毕业后直接研读。2d/platformer/完整 2D 平台跳跃游戏能看到本例的角色控制器、平台碰撞与收集物逻辑如何组装成一个可玩关卡。3d/ik/3D 反向动力学示例FABRIK、LookAt IK 等想从正运动学往 IK 走时的下一站。源码获取方式git clone https://gitcode.com/GitHub_Trending/go/godot-demo-projects【免费下载链接】godot-demo-projectsDemonstration and Template Projects项目地址: https://gitcode.com/GitHub_Trending/go/godot-demo-projects创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价