关于 animation-system
面向 Godot 4.3+ 开发者的动画系统技能,介绍 AnimationPlayer、AnimationTree、精灵动画及 3D 骨骼动画,示例使用 GDScript 和 C#。
主要功能
- 01AnimationPlayer 播放与控制
- 02AnimationTree 状态机和混合
- 03精灵帧动画
- 04动画信号与方法调用轨道
- 053D 骨骼修饰器与 IK
- 06动画标记和重定向
适用场景
- 01为角色设置行走与攻击动画
- 02在状态间平滑切换动画
- 03在动画帧触发命中框或音效
- 04为 3D 角色配置骨骼 IK
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill animation-system安装后在 Claude Code 中输入/animation-system确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/animation-markers.mdblend-spaces.mdbone-constraints.mdcommon-pitfalls.mdcommon-recipes.mdik-recipes.mdik-solver-comparison.mdretargeting.mdskeleton-modifiers.mdsprite-animation.mdstate-machine-examples.md详细介绍
Godot 4.3+ 中的动画系统
所有示例均适用于 Godot 4.3+,不使用已弃用的 API。先展示 GDScript,再展示 C#。
**相关技能:**用于管理游戏状态的 state-machine,用于驱动动画的移动功能的 player-controller,用于构建可复用动画组件的 component-system,用于 TileMaps、视差滚动、2D 光照和画布图层组织的 2d-essentials,用于 AnimationTree 和 3D 动画混合的 3d-essentials,用于着色器驱动的受击闪白和溶解效果的 shader-basics,以及用于与关键帧动画并行实现代码驱动运动的 tween-animation。
1. 核心概念
AnimationPlayer 与 AnimationTree
| 节点 | 用途 | 复杂度 | 说明 |
|---|---|---|---|
AnimationPlayer | 简单播放、单次效果 | 低 | 直接播放、停止或排队播放单个动画片段 |
AnimationTree | 混合、过渡、分层动画 | 中到高 | 使用状态机和混合树实现平滑过渡 |
**经验法则:**从 AnimationPlayer 开始。当需要在动画之间进行混合(行走/奔跑混合、方向移动、上半身/下半身分层)时,再添加 AnimationTree。
动画工作流
1. Create AnimationPlayer node → holds all animation clips
2. Add tracks in the Animation panel → keyframe properties, methods, audio
3. (Optional) Add AnimationTree → blend/transition logic
4. Trigger from code → play(), travel(), set parameters
2. AnimationPlayer 基础知识
场景结构
Character (CharacterBody2D)
├── Sprite2D
└── AnimationPlayer
AnimationPlayer 可以为任意兄弟节点或子节点上的任何属性制作动画:精灵帧、调制、位置、旋转、缩放、可见性、碰撞形状的禁用状态、方法调用(Call Method 轨道)、音频播放(Audio Playback 轨道)。
GDScript — 基本播放
extends CharacterBody2D
@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:
velocity = input_dir * 200.0
anim_player.play("walk")
else:
velocity = Vector2.ZERO
anim_player.play("idle")
move_and_slide()
C# — 基本播放
using Godot;
public partial class Character : CharacterBody2D
{
private AnimationPlayer _animPlayer;
public override void _Ready()
{
_animPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
}
public override void _PhysicsProcess(double delta)
{
Vector2 inputDir = Input.GetVector("ui_left", "ui_right", "ui_up", "ui_down");
if (inputDir != Vector2.Zero)
{
Velocity = inputDir * 200.0f;
_animPlayer.Play("walk");
}
else
{
Velocity = Vector2.Zero;
_animPlayer.Play("idle");
}
MoveAndSlide();
}
}
如果动画已经在播放时调用
play()并传入相同的动画名称,则不会有任何效果(不会重新开始)。每帧调用都是安全的。
播放控制
anim_player.play("attack")
anim_player.play_backwards("attack")
anim_player.queue("idle") # play after current
anim_player.stop()
anim_player.pause()
anim_player.play() # resume from paused position
anim_player.speed_scale = 2.0
anim_player.seek(0.5)
_animPlayer.Play("attack");
_animPlayer.PlayBackwards("attack");
_animPlayer.Queue("idle");
_animPlayer.Stop();
_animPlayer.Pause();
_animPlayer.Play();
_animPlayer.SpeedScale = 2.0f;
_animPlayer.Seek(0.5);
3. 动画信号
func _ready() -> void:
anim_player.animation_finished.connect(_on_animation_finished)
func _on_animation_finished(anim_name: StringName) -> void:
match anim_name:
"attack":
anim_player.play("idle")
"death":
queue_free()
public override void _Ready()
{
_animPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
_animPlayer.AnimationFinished += OnAnimationFinished;
}
private void OnAnimationFinished(StringName animName)
{
if (animName == "attack")
_animPlayer.Play("idle");
else if (animName == "death")
QueueFree();
}
方法调用轨道
添加 Call Method 轨道,在动画的精确帧触发游戏逻辑(在第 5 帧生成投射物、在命中帧播放音效、挥击期间启用命中框)。在 Animation 面板中:Add Track → Call Method Track → 选择目标节点 → 添加关键帧 → 设置方法名称和参数。
func spawn_projectile() -> void:
var bullet := preload("res://scenes/bullet.tscn").instantiate()
get_parent().add_child(bullet)
bullet.global_position = $Muzzle.global_position
func enable_hitbox() -> void:
$HitboxArea/CollisionShape2D.disabled = false
4. 精灵帧动画
2D 角色动画有两种实现方式:AnimatedSprite2D(快速实现,仅支持帧动画)和 AnimationPlayer + Sprite2D(完整的属性动画)。简单角色可选用 AnimatedSprite2D;如果还需要同步为命中框、粒子、音效或其他属性制作动画,则使用 AnimationPlayer。
完整的 GDScript 和 C# 示例(通过
Input.get_vector和flip_h驱动的 CharacterBody2D 行走动画)请参阅 references/sprite-animation.md。
往返播放(Godot 4.7+)
SpriteFrames 使用 set_animation_loop_mode(anim, SpriteFrames.LOOP_PINGPONG)(也可使用 LOOP_NONE、LOOP_LINEAR)替代布尔值 set_animation_loop()(已弃用);适用于 AnimatedSprite2D 和 AnimatedSprite3D。
GDScript 和 C# 代码片段请参阅 references/sprite-animation.md。
5. AnimationTree — 标准状态机
场景结构
Character (CharacterBody2D)
├── Sprite2D
├── AnimationPlayer ← holds all clips
└── AnimationTree ← controls blending/transitions
(tree_root = AnimationNodeStateMachine or AnimationNodeBlendTree)
**设置:**将 AnimationTree 添加为 AnimationPlayer 的兄弟节点。将 anim_player 设置为指向 AnimationPlayer。将 active = true。选择根节点:AnimationNodeStateMachine(带过渡的离散状态)或 AnimationNodeBlendTree(连续混合)。
状态机播放
典型模式:从 anim_tree["parameters/playback"] 缓存 AnimationNodeStateMachinePlayback,在游戏逻辑代码中调用 travel("state")(travel() 会平滑过渡;start() 会立即切换),并通过 get_current_node() 查询当前活动状态。
完整的 GDScript 和 C# CharacterBody2D 示例,请参阅 references/state-machine-examples.md。
混合树 — BlendSpace1D / BlendSpace2D
如需连续混合(根据速度在步行↔跑步之间切换,或根据 2D 向量实现 4/8 方向移动),请将根节点设为 AnimationNodeBlendTree,添加 BlendSpace1D 或 BlendSpace2D,并在每帧通过游戏逻辑代码设置 anim_tree["parameters/BlendSpace2D/blend_position"]。
关于混合点的放置,以及驱动 1D 速度混合和 2D 方向混合的 GDScript + C# 代码,请参阅 references/blend-spaces.md。
命名混合点(Godot 4.7+)
add_blend_point() 新增了可选的 name 参数(请传入名称:空名称将被弃用);使用 find_blend_point_by_name() 查找混合点。
GDScript + C# 代码片段请参阅 references/blend-spaces.md。
⚠️ Godot 4.7 中的变更:
AnimationNodeBlendSpace1D/2D中的 boolsync已弃用,现由sync_mode属性(C#:SyncMode)取代。该属性接受以下枚举值:SYNC_MODE_NONE(默认值——非活动动画会冻结)、SYNC_MODE_INDEPENDENT(旧版sync = true)、SYNC_MODE_CYCLIC_MUTABLE、SYNC_MODE_CYCLIC_CONSTANT。如果在 4.6 中能正常混合的树不再正确过渡,请为每个混合空间设置sync_mode。完整的枚举语义说明:references/blend-spaces.md。
6. 骨骼修改器(3D,4.4+)
LookAtModifier3D(Godot 4.4+)
以程序化方式旋转骨骼,使其朝向世界空间中的目标。适用于头部追踪和眼神接触,无需额外的动画片段。
带角度限制和影响混合的完整 GDScript 和 C# 示例,请参阅 references/skeleton-modifiers.md。
⚠️ Godot 4.7 中的变更:
LookAtModifier3D.relative的默认值为false(相对于静止姿势旋转);只有 4.6.0 使用true。设置relative = true可恢复原有行为——详情请参阅 references/skeleton-modifiers.md。
BoneConstraint3D(Godot 4.5+)
AimModifier3D、CopyTransformModifier3D 和 ConvertTransformModifier3D 从同一骨架上的另一个骨骼获取参考对象(用于镜像、绑定次级骨架、骨骼间瞄准);从 Godot 4.6 开始,参考对象也可以是 Node3D(REFERENCE_TYPE_NODE)。
完整深入介绍,包括修改器表格、场景结构,以及 AimModifier3D 和 CopyTransformModifier3D 的 GDScript 和 C# 示例,请参阅 references/bone-constraints.md。
SpringBoneSimulator3D(Godot 4.4+)
模拟骨骼上的弹簧物理效果——头发、披风、尾巴和天线会以程序化方式弹跳和摇摆。将其添加为 Skeleton3D 的子节点,然后在检查器中配置弹簧链(根骨骼、末端骨骼、半径、刚度、阻力、重力)。
属性参考表,以及针对不同用途(头发、天线、披风)的推荐起始值,请参阅 references/skeleton-modifiers.md。
动画标记(Godot 4.4+)
片段内的命名点或区域(时间轴 → 插入标记……),可用于子区域循环和帧级精确事件,无需拆分片段;使用 play_section_with_markers() 播放某个区域。
工作流和 GDScript + C# 代码请参阅 references/animation-markers.md。
动画重定向(Godot 4.3+)
Godot 4.3 会在导入 .glb/.gltf 时,通过 SkeletonProfile(例如 SkeletonProfileHumanoid)将动画从一个骨架重定向到另一个骨架。之后,动画会以通用配置文件骨骼名称为目标,因此任何匹配的骨架都能播放这些动画。
完整的导入停靠面板设置步骤,请参阅 references/retargeting.md。
7. IKModifier3D — 求解器对比(Godot 4.6+)
Godot 4.6 新增了 IKModifier3D,这是骨骼 IK 求解器的基类,并提供五种可直接使用的求解器:TwoBoneIK3D、CCDIK3D、FABRIK3D、JacobianIK3D 和 SplineIK3D。这些都是 Skeleton3D 的 SkeletonModifier3D 子节点,可与其他修改器(例如 LookAtModifier3D)协同工作。
根据骨骼链选择:TwoBoneIK3D 适用于恰好由两根骨骼组成的肢体(需要一个极向节点),FABRIK3D 适用于没有关节限制的简单骨骼链,CCDIK3D 适用于关节有限制的情况,SplineIK3D 用于沿 Path3D 移动,JacobianIK3D 则适合平滑、有机的动作,但跟踪速度较慢。
完整的求解器对比表和选择指南,请参阅 references/ik-solver-comparison.md。
完整的 GDScript 和 C# 示例,包括带影响权重混合的手臂伸展(CCDIK3D)、不平坦地形上的脚部放置(FABRIK3D + 射线检测),以及基础 FABRIK 手臂 IK 设置,请参阅 references/ik-recipes.md。
8. 常用示例
两个贴近游戏玩法的动画示例:受击闪白调制补间,以及使用 AnimationPlayer 的 Call Method 轨道实现带缓冲的攻击连招。
完整的 GDScript 和 C# 代码(受击闪白、带连招窗口缓冲的攻击连招),请参阅 references/common-recipes.md。
9. 常见问题
快速症状 → 原因 → 修复表,涵盖动画突然跳变而非平滑混合、AnimationTree 未激活、travel() 未发生状态切换、轨道节点路径错误、Call Method 轨道无响应、混合参数无效,以及每帧调用 play() 导致的重置。
完整表格请参阅 references/common-pitfalls.md。
10. 实现检查清单
- AnimationPlayer 是动画节点的直接子节点(没有更深层的嵌套)
- 所有动画轨道节点路径均有效(场景结构调整后没有失效引用)
- AnimationTree 的
active已设为true,且anim_player指向正确的 AnimationPlayer - 状态机转换设置了合适的淡入淡出时间(响应迅速的游戏玩法建议使用 0.1–0.2s)
- 循环动画(待机、行走、跑步)在 Animation 面板中将循环模式设为 Loop
- 单次播放动画(攻击、跳跃、死亡)将循环模式设为 None
- 使用 Call Method 轨道处理游戏事件(启用/禁用命中框、生成投射物、播放音效)
- 每帧都从游戏玩法代码设置混合参数(而不只是在状态变化时设置)
- 需要后续逻辑的单次播放动画已连接
animation_finished信号 - 头部/眼部跟踪使用
LookAtModifier3D,而非手动旋转骨骼(Godot 4.4+) - 头发、披风和尾巴使用
SpringBoneSimulator3D,而非自定义物理脚本(Godot 4.4+) - 共享动画库使用
SkeletonProfileHumanoid进行重定向(Godot 4.3+) - 骨骼间瞄准/复制约束使用
AimModifier3D/CopyTransformModifier3D,而非手动编写骨骼变换代码(Godot 4.5+) - 手臂/腿部 IK 使用
IKModifier3D子类(两骨骼肢体使用带极向节点的TwoBoneIK3D,较长的骨骼链使用FABRIK3D或CCDIK3D),而非自定义 IK 脚本(Godot 4.6+)