山高月小,水落石出。

Godot AnimationTree

AnimationTree 是 Godot 动画系统的决策层。它本身不包含任何动画数据,而是指向一个已有的 AnimationPlayer,在运行时根据你的逻辑(状态切换、输入方向、速度值)动态决定“现在该播放什么、如何混合”。当你发现需要在多条动画之间平滑过渡、按方向混合,或在基础动画上叠加一次性动作时,就该引入 AnimationTree 了。 🧭 三种核心组织方式:先选对“大脑” AnimationTree 的根节点决定了它的调度方式,最常用的是以下三种: 根节点类型 解决的问题 典型场景 AnimationNodeStateMachine 离散状态的切换与过渡 idle ↔ walk ↔ jump ↔ attack AnimationNodeBlendSpace2D 连续方向/速度的混合 8 方向移动、walk→run 的速度混合 AnimationNodeBlendTree 分层与叠加(配合 OneShot 等节点) 走路时开枪、受击闪烁叠加在基础动画上 实际项目中,状态机与混合空间通常是嵌套配合的:状态机负责“当前处于什么大状态”(如 Locomotion),而该状态内部的具体方向或速度变化,交给嵌套的 BlendSpace2D 处理。 ⚙️ 前置设置:两步让树跑起来 在写任何代码之前,AnimationTree 需要两个明确的配置,否则它不会驱动任何东西: anim_player 指向数据源:在检查器中将 AnimationTree 的 anim_player 属性指向场景中已有的 AnimationPlayer。 active = true:AnimationTree 默认不激活,必须在检查器中勾选,或在 _ready() 中设置 active = true。 🧩 示例一:最简状态机 —— travel() 事件驱动 适用场景:由代码逻辑直接命令的状态切换,如跳跃、攻击、死亡。 树的结构(在 AnimationTree 编辑器中创建 AnimationNodeStateMachine,添加状态并连线): 1 2 3 4 StateMachine ├── Idle ├── Walk └── Jump 关键代码:状态机播放控制器通过 playback 参数获取,travel() 会立即中断当前状态并转向目标状态,并自动寻找最短路径。 ...

November 4, 2026 · 3 min · zwdart
山高月小,水落石出。

Godot AnimationPlayer

AnimationPlayer 是 Godot 动画系统的数据核心。与“即用即弃”的 Tween 不同,它把动画作为资源保存在节点里,通过可视化的时间轴进行编排,可以在编辑器中精细调整节奏,再用代码决定何时播放哪一段。如果你的动画涉及多个属性、需要精确到帧的时序,或者包含音效、函数调用等非属性事件,AnimationPlayer 是比 Tween 更合适的选择。 🧱 先建立正确的场景结构 AnimationPlayer 继承自裸 Node,而不是 Node2D 或 Node3D。这意味着它不传递变换——如果把带有 2D/3D 变换的节点设为它的子节点,子节点不会继承父级的位移、旋转或缩放,视觉上会出现位置偏移或异常。 正确的结构是让 AnimationPlayer 与被动画的节点平级: 1 2 3 Player (CharacterBody2D) ├── Sprite2D └── AnimationPlayer AnimationPlayer 可以通过轨道路径驱动任意兄弟或子节点的属性:位置、旋转、缩放、modulate、visible、碰撞形状的 disabled 状态,甚至方法调用和音频播放。 🗂️ 轨道类型:不止是属性 在动画面板中点击“添加轨道”,你会看到多种类型。常用的是以下四种: 轨道类型 作用 典型用途 属性轨道 (Property / Value) 插值任意属性 位置、旋转、透明度、着色器参数 方法轨道 (Call Method) 在精确时间点调用函数 生成伤害判定、播放音效、切换状态 音频轨道 (Audio Playback) 将音频锁定在时间轴上 脚步声与落脚点精确同步 贝塞尔轨道 (Bezier) 用曲线精细控制数值节奏 非线性的 UI 动效、特殊缓动 方法轨道的关键配置:默认的调用模式是 CALL_MODE_CONTINUOUS,在关键帧前后拖拽播放头时可能每帧重复触发。对于“伤害判定只该发生一次”的逻辑,必须在代码中将调用模式设为 CALL_MODE_DISCRETE,确保函数在越过关键帧时只执行一次。 ▶️ 代码控制:播放、混合与队列 基础播放与状态驱动 1 2 3 4 5 6 7 8 @onready var anim_player: AnimationPlayer = $AnimationPlayer func _physics_process(_delta: float) -> void: var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down") if input_dir != Vector2.ZERO: anim_player.play("walk") else: anim_player.play("idle") 一个重要的细节:对正在播放的同一动画重复调用 play() 不会重新开始,也不会报错。因此可以在 _physics_process 中放心地每帧调用 play(),根据状态切换动画。 ...

November 4, 2026 · 2 min · zwdart
山高月小,水落石出。

Godot Tween

Tween 是 Godot 中用于“在代码里顺手做一小段动画”的轻量级工具。它的核心用途很单纯:将一个属性从当前值平滑地插值到目标值,创建后自动运行,完成后自动释放,非常适合 UI 反馈、简单的位移/透明度变化、镜头震动这类“即用即弃”的动效。 🧱 先建立正确的心智模型 使用 Tween 时,有几个前置规则需要先刻在脑子里: ① 必须用 create_tween() 创建 Tween.new() 是无效的,不能用来做补间。正确的入口只有两个: 1 2 3 4 5 # 方式一:从节点创建,Tween 会绑定到该节点的生命周期 var tween = create_tween() # 方式二:从场景树创建,不绑定特定节点 var tween = get_tree().create_tween() ② Tween 本质上是一条“时间线” 你往这条时间线上添加的每一个 tween_property()、tween_callback()、tween_interval(),都是一个 Tweener。默认情况下,这些 Tweener 会按添加顺序一个接一个地串行执行。 ③ 默认是串行,set_parallel(true) 可以改为并行 这是控制 Tween 行为最关键的一个开关,后面会用具体示例展开。 ✂️ 核心 API:你只需要先掌握这几个 方法 作用 tween_property(object, property, final_val, duration) 最核心的方法,在 duration 秒内将 property 插值到 final_val tween_callback(callable) 在时间线的某个点执行一个函数 tween_interval(time) 在时间线上插入一段纯等待 set_parallel(true) 让后续的 Tweener 并行执行,而不是串行 chain() 从并行模式切回串行模式 set_loops(n) 设置循环次数,0 或不传参表示无限循环 set_ease() / set_trans() 控制缓动曲线(加速/减速的节奏) .from(value) 指定起始值,不依赖属性的当前值 .as_relative() 将目标值视为相对偏移量 🍳 常用可运行示例 以下示例均假设脚本挂在某个节点上,可以直接复制到 _ready() 或按钮回调中运行。 ...

November 4, 2026 · 3 min · zwdart
山高月小,水落石出。

Godot Animation介绍

Godot 的动画系统以简洁但极具深度著称。理解它的关键在于建立一个清晰的层次观:Tween、AnimationPlayer 和 AnimationTree 三者并非替代关系,而是分别针对不同场景、逐级递进的工具。 🗺️ 先看全景:你该在什么时候用什么? 社区里一条非常实用的“黄金法则”是:从 AnimationPlayer 开始;当你需要动画之间的混合、过渡或分层时,再引入 AnimationTree。 工具 最适合的场景 关键特征 Tween 代码驱动的一次性短动画:按钮悬停、屏幕震动、UI 淡入、伤害闪烁 纯代码创建,运行一次后自动释放 AnimationPlayer 需要在编辑器中“编排”的动画:精灵帧序列、复杂运动、过场动画、UI 过渡 可视化时间轴,可复用,能驱动几乎任何属性 AnimationTree 需要状态管理或混合的角色动画:idle→walk→run、8 方向移动、上下半身分层 包裹 AnimationPlayer,用状态机或混合树来调度播放 你的学习路径可以按照 Tween → AnimationPlayer → AnimationTree 的顺序推进,下面逐层展开。 🌱 第一层:Tween —— 代码里的“一次性动效” Tween 是三者中最轻量的。它不活在场景树里,而是由代码通过 create_tween() 创建,专注于将某个属性从当前值平滑插值到目标值。 1 2 3 4 5 # 让节点在 1 秒内移动到 (500, 300) var tween = create_tween() tween.tween_property(self, "position", Vector2(500, 300), 1.0) .set_ease(Tween.EASE_OUT) .set_trans(Tween.TRANS_CUBIC) 核心心智模型:Tween 是“即用即走”的。如果只是一个按钮弹一下、一个面板滑进来,用它最直接,不需要在场景里挂节点,也不需要打开动画面板。 ✂️ 第二层:AnimationPlayer —— 你的万能动画剪辑台 AnimationPlayer 是整个动画系统的数据基础。它本身是一个 Node,内部可以存放多条动画片段,每条动画由若干轨道组成,轨道上放置关键帧。 关键概念:轨道与关键帧 一条轨道绑定到“某个节点的某个属性”(例如 Sprite2D:position)。关键帧记录该属性在某一时刻的值;两个关键帧之间,引擎会自动插值,让属性平滑变化。 ...

November 4, 2026 · 2 min · zwdart