Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
2D 精灵动画
前言
在本教程中,你将学习如何使用 AnimatedSprite2D 类和 AnimationPlayer 创建 2D 动画角色。 通常,当你创建或下载动画角色时,它将以两种方式之一出现:作为单独的图像或作为包含所有动画帧的单个精灵表。 两者都可以在 Godot 中使用 AnimatedSprite2D 类进行动画处理。
首先,我们将使用 AnimatedSprite2D 对单个图像集合进行动画处理。 然后我们将使用此类对精灵表进行动画处理。 最后,我们将学习另一种使用 AnimationPlayer 和 Sprite2D 的 Animation 属性来制作精灵表动画的方法。
备注
以下示例的美术资产由 https://opengameart.org/users/ansimuz 和 https://opengameart.org/users/tgfcoder 共同提供。
AnimateSprite2D 与若干单独的图片
在这个情况下,你有一组图像,每一个都包含你角色的动画的一帧。 对于这个例子,我们将使用以下动画:

你可以在这里下载图片:2d_sprite_animation_assets.zip
解压缩这些图像并将它们放在项目文件夹中。 使用以下节点布置场景树:

备注
根节点也可以是 Area2D 或 RigidBody2D。动画仍然会以同样的方式制作。一旦动画完成,你就可以为 CollisionShape2D 形状分配一个形状。更多信息请参见物理介绍。
现在选中 AnimatedSprite2D
,并在它的 SpriteFrames 属性中,选择“新建 SpriteFrames”。

点击新的 SpriteFrames 资源,你会看到一个新的面板出现在编辑器窗口的底部:

将这 8 张独立的图片从左边的“文件系统”面板拖放到“动画帧”面板的中间部分。在左边,将动画名称从“default”更改为“run”。

使用 过滤动画(Filter Animations) 输入右上角的“播放(Play)”按钮预览动画。 你现在应该可以看到动画在视口中播放。 然而,它有点慢。 要解决此问题,请将 SpriteFrames 面板中的 Speed (FPS) 设置更改为 10。
你可以通过单击“添加动画”按钮并添加其他图像来添加其他动画。
控制动画
动画完成后,你可以通过代码中的 play()
和 stop()
方法控制动画。 这里有一个简单的例子,按住右方向键播放动画,松开后就停下。
extends CharacterBody2D
@onready var _animated_sprite = $AnimatedSprite2D
func _process(_delta):
if Input.is_action_pressed("ui_right"):
_animated_sprite.play("run")
else:
_animated_sprite.stop()
using Godot;
public partial class Character : CharacterBody2D
{
private AnimatedSprite2D _animatedSprite;
public override void _Ready()
{
_animatedSprite = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
}
public override void _Process(double delta)
{
if (Input.IsActionPressed("ui_right"))
{
_animatedSprite.Play("run");
}
else
{
_animatedSprite.Stop();
}
}
}
AnimateSprite2D 与精灵表
你还可以很方便地使用 AnimatedSprite2D
把精灵表做成动画。我们会用到这张公共领域的精灵表:

右键单击图片,选择“图片另存为”来下载图片,然后将图片复制到项目文件夹中。
设置场景树的方法与之前使用单独图片的时候相同。选中 AnimatedSprite2D
后在 SpriteFrames 属性里选择“新建 SpriteFrames”。
点击创建出来的 SpriteFrames 资源。底部面板出现后,这次我们选择“从精灵表中添加帧”。

在弹出的打开文件对话框中,选择你的精灵表。
接下来会打开一个新的窗口,里面会显示刚才的精灵表。你首先需要修改精灵表中纵向和横向的图片数量,我们的这张精灵表里横向有四张图片、纵向有两张。

然后,在精灵表中选择动画中想要包含的帧。这里我们选中上面的四个,然后点击“添加 4 帧”来创建动画。

现在你就可以看到在底部面板的动画列表里看到这个动画了。双击 default(默认),然后把动画的名称改成 jump(跳跃)。

最后,点击 SpriteFrames 编辑器上的播放按钮,你的青蛙就能跳起来了!

AnimationPlayer 与精灵表
使用 Sprite Sheet 时制作动画的另一种方法是使用标准 Sprite2D 节点来显示纹理,然后使用 AnimationPlayer 对纹理之间的变化进行动画处理 。
考虑一下这个包含 6 帧动画的精灵表:

右键单击图片,选择“图片另存为”下载图片,然后将图片复制到项目文件夹中。
我们的目的是,循环着一个接一个地显示这些图像。 首先布置你的场景树:

备注
根节点也可以是 Area2D 或 RigidBody2D。动画仍然会以同样的方式制作。一旦动画完成,你就可以为 CollisionShape2D 形状分配一个形状。更多信息请参见物理介绍。
将精灵表拖拽到 Sprite 的 Texture 属性里,你会看到整个清单显示在屏幕上。要把它分割成单独的帧,请在“检查器”中展开 Animation 部分,将 Hframes 设置为 6
。Hframes 和 Vframes 是精灵表中水平和垂直帧的数量。

现在尝试更改 Frame 属性的值。 你会看到它的范围从 0
到 5
,Sprite2D 显示的图像也会相应变化。 这是我们要设置动画的属性。
选中 AnimationPlayer
,然后点击 "动画" 按钮,然后点击 "新建" 按钮. 将新动画命名为 "walk". 将动画长度设置为 0.6
,点击 "Loop" 按钮,让动画重复播放.

现在选中 Sprite2D
节点,然后单击钥匙图标,添加一个新轨道。

继续在时间轴的每一点添加帧(默认为 0.1
秒),直到你得到了从 0 到 5 的所有帧。你会看到这些帧出现在动画轨道上:

按下动画上的“播放”键,看看效果如何。

控制 AnimationPlayer 动画
与 AnimatedSprite2D 一样,你可以使用 play()
和 stop()
方法通过代码控制动画。 同样,这里是一个在按住右箭头键时播放动画的示例,并在释放该键时停止动画。
extends CharacterBody2D
@onready var _animation_player = $AnimationPlayer
func _process(_delta):
if Input.is_action_pressed("ui_right"):
_animation_player.play("walk")
else:
_animation_player.stop()
using Godot;
public partial class Character : CharacterBody2D
{
private AnimationPlayer _animationPlayer;
public override void _Ready()
{
_animationPlayer = GetNode<AnimationPlayer>("AnimationPlayer");
}
public override void _Process(double delta)
{
if (Input.IsActionPressed("ui_right"))
{
_animationPlayer.Play("walk");
}
else
{
_animationPlayer.Stop();
}
}
}
备注
If updating both an animation and a separate property at once
(for example, a platformer may update the sprite's h_flip
/v_flip
properties when a character turns while starting a 'turning' animation),
it's important to keep in mind that play()
isn't applied instantly.
Instead, it's applied the next time the AnimationPlayer is processed.
This may end up being on the next frame, causing a 'glitch' frame,
where the property change was applied, but the animation was not.
If this turns out to be a problem, after calling play()
, you can call advance(0)
to update the animation immediately.
总结
这些示例说明了可在 Godot 中用于 2D 动画的两个类。AnimationPlayer
比 AnimatedSprite2D
稍微复杂一些,但它提供了额外的功能,因为你还可以为其他属性(如位置或比例)设置动画。 类 AnimationPlayer
也可以与 AnimatedSprite2D
一起使用。 尝试看看什么最适合你的需求。