如何在 Godot 4 中导入精灵图
Godot 自己就能切精灵图,所以导入通常是四次点击。 真正让人搭进去一个下午的是它周围那些事:美术出来是糊的、 切图器不认紧凑图集、摄像机一动精灵就抖。 这三件事各有各的确切成因。
别的都先放一放:先把模糊关掉
Godot 4 默认对 2D 贴图做线性过滤。 对照片来说这是对的。对一个放大 4 倍的 32×32 精灵来说, 这意味着每个像素都被抹进了它的邻居里, 结果看着像一张从 2004 年抢救回来的 JPEG。 这是 Godot 像素画最常见的抱怨,而它只是一个设置。
Project → Project Settings → Rendering → Textures → Canvas Textures → Default Texture Filter,把它设成 Nearest。 它作用于整个项目,而这正是你想要的—— 一个每加一个新精灵都得记着去改的逐节点修法,不算修法。
如果项目是混着来的——像素画角色叠在平滑着色的背景上—— 那就把默认值留成 Linear,改成逐节点覆盖。 每个 CanvasItem 在检查器里都有 Texture → Filter, 而且在父节点上设了会被子节点继承, 所以在装着你那些精灵的容器上覆盖一次,就把它们全盖住了。
注意这一点在版本之间变过。Godot 3 里过滤是贴图上的一个导入标志, 所以老教程会叫你去 Import 面板里取消勾选「Filter」。 Godot 4 里那个标志没了—— 过滤是「画这张贴图的那个东西」的属性,不是贴图的属性。
1. 把文件放进项目
把 PNG 复制到项目文件夹下的任何地方。 编辑器窗口下次获得焦点时 Godot 就会发现它、导入它, 并在旁边写一个小小的 yoursheet.png.import 文件。 那个 .import 文件该进版本控制; 它指向的 .godot/ 文件夹不该。
从美术软件里重新导出覆盖过去就行—— Godot 会重新导入,所有引用它的地方都会跟着更新。 如果它看上去卡在了旧版本上,删掉 .godot/imported/ 再重开项目,可以强制一次干净的重导入。
2. 挑一个和你手上东西对得上的节点
有三个节点能读精灵图,而挑错了正是有些人最后在手动做动画的原因。
AnimatedSprite2D
角色动画——待机、走路、攻击
它持有一个 SpriteFrames 资源, 里面装着一组具名动画,每个各有自己的帧列表和 FPS。 你几乎总是想要这个。它还能替你切图。
Sprite2D + Hframes/Vframes
一个由你自己驱动的均匀网格
把 Hframes 和 Vframes 设成网格尺寸, 然后用 Frame 属性挑格子。 当这个对象已经由 AnimationPlayer 控制, 而你只想把 frame 和位置、旋转一起打关键帧时,这个有用。
TileMapLayer 上的 TileSet
这是一套地块,不是一段动画
一张地形地块图是另一个问题,有另一个编辑器。 建一个 TileSet,把这张图作为图集源加进去,在那里设置地块尺寸。
3. 用 AnimatedSprite2D 切图
添加一个 AnimatedSprite2D。在检查器里点 Sprite Frames → New SpriteFrames, 然后点开这个资源,编辑器底部会出现 SpriteFrames 面板。
那个面板里,工具栏第二个按钮是从精灵图添加帧(第一个是添加单张图片文件)。 选中你的 PNG,会弹出一个带网格叠加的对话框:
Horizontal / Vertical——多少列、多少行, 不是单元格的像素尺寸。一张 8×4、每帧 32px 的图填的是 8 和 4。
Separation——格子之间的空隙,如果导出器留了的话。
Offset——网格外围的一圈边距。
然后按顺序点选你要的帧。这一步最容易被漏掉: 这个对话框默认不会全选,而且你点击的顺序就是帧播放的顺序。 在一行上拖过去可以一次选完。 把动画名从 default 改成一个真名字,设好 FPS, 再打开或关掉循环开关。
一张图通常装着好几段动画。先把动画都建出来, 然后每段动画跑一次这个对话框,每次只选那一行—— 一个装着整张图所有帧的 default 动画,之后是没法用的。
在定下来之前,如果你不确定帧顺序或者帧率对不对,精灵动画预览器能在浏览器里以任意 FPS 播放这张图,比在编辑器里来回折腾快得多。
4. 当 Godot 的切图器搞不定时
内置切图器把一张图建模成一个间距固定的均匀网格。 这覆盖了大多数手工做的图,以及 Aseprite 导出的所有横条。 它覆盖不了:
紧凑图集。帧大小不一、为省空间紧密排布、没有统一网格—— 也就是 TexturePacker 或者任何「打包精灵」选项的输出。 Godot 没有描述这类图集的 JSON 或 .plist 的导入器; 你得为每一帧手动建一个 AtlasTexture 资源, 一个个手填区域矩形。
除非有东西替你把这些资源写好。精灵图生成器在导出图集的同时可以导出一份 SpriteFrames 资源—— 清单格式选 Godot 4(SpriteFrames), 你会拿到一个 .tres,里面每一帧一个 AtlasTexture, 区域矩形都填好了,裁边的偏移写在各自的 margin 里, 所以裁过边的帧照样占着它原来的位置。 把 .tres 和 PNG 一起放在项目根目录, 拖到 AnimatedSprite2D 上就能播。 紧凑排布和裁边这两种情况一次解决; 帧率写的是 10,之后在检查器里就是一个可以改的字段。
间距不一致的网格, 这在图是手工拼的、或者导出后又被裁过时会出现。
需要先裁边或者重排才能用的帧。
这三种情况都一样:在 Godot 外面把图切成单张 PNG, 然后把它们拖进 SpriteFrames——那条路对网格没有任何要求。精灵图切割工具能按网格切,也能自动识别—— 它去找不透明像素连成的独立区域,在紧凑图集上照样管用—— 并给你一个装着编号帧的 ZIP。 Godot 对拖进来的文件做自然排序, 所以 run_2.png 会排在 run_10.png 前面。
5. 值得改的那几个导入选项
在 FileSystem 面板里选中这个 PNG,切到 Import 标签页。 默认值对 2D 来说是合理的,但有两个对像素画值得看一眼:
Compress → Mode 应该保持 Lossless。 VRAM Compressed 是块压缩——它在大贴图上省内存, 在带硬色块边界的小精灵上则会把画面搅烂,而像素画恰好就是后者。
Mipmaps → Generate 在 2D 里应该保持关闭。 Mipmap 是预先模糊好的缩小副本,用于贴图被画得小于原始尺寸时; 给一张精灵图打开它,等于刚把模糊关掉又把它请回来。
Process → Fix Alpha Border 应该保持开启。 它把完全透明像素的颜色通道填成最近的不透明颜色, 这样在精灵边缘附近做过滤时就不会把黑色拉进来、留下一圈暗边。 在 Nearest 过滤下它无害,而当下游某个环节确实做了过滤时,它救你一命。
改完任何东西都要按 Reimport——这个标签页不会自动应用。
6. 让整个游戏按整数倍缩放
Nearest 过滤阻止的是贴图被模糊。 它阻止不了小数倍缩放,而那会产生另一个经典瑕疵: 有些像素占两个屏幕像素宽、旁边的占三个, 于是精灵一动起来就闪、就晃。
在 Display → Window → Stretch 下, 把 Mode 设成 canvas_items, 把 Scale Mode 设成 integer。 这样 Godot 只会按整数倍缩放视口,多出来的部分加黑边, 而不是按 2.4 倍缩放然后留给你去解释那个抖动。
还有两样东西会在事后把这件事破坏掉。 一个 zoom 是 2.5 这类值的 Camera2D,以及一个不是整数的节点 scale—— 包括由补间动画在两个值之间缓动出来的那种。 如果精灵只在播动画时抖,去查补间。
相关的一点:把你美术的原始分辨率一次定下来,并按它作画, 而不是在导入前先把精灵放大 4 倍。 那样贴图更大却没有多出任何细节,而 Godot 反正会替你缩放。 如果你接手的美术已经被放大过了,像素画缩放工具能识别出倍数,把它还原回原始尺寸。
常见故障
游戏跑起来像素画是糊的
Default Texture Filter 还是 Linear。 去 Project Settings → Rendering → Textures → Canvas Textures。 在 Godot 4 里这不是导入设置,不管 Godot 3 的教程怎么说。
编辑器里很锐利,一运行就糊
拉伸模式在带过滤地放大视口。 在 Display → Window → Stretch 下把 Scale Mode 设成 integer。
精灵边上出现了下一帧的细线
声明的网格和这张图对不上——通常是格子之间有没声明的间距。 每往右一列偏得更多一点,所以要检查最后一列,不是第一列。
动画的播放顺序是乱的
切图对话框记录的是你点击帧的顺序,不是它们在图上的位置。 清掉这段动画,从左到右重新选一遍。
只有一段动画,里面装着所有东西
对话框在整张图上只跑了一次。先给每个动作各建一段动画, 然后每段跑一次切图,每次只选那一行。
浅色背景上的精灵有一圈暗色描边
透明像素的颜色通道里带着黑色,而某个环节在跨边缘做过滤。 在 Import 标签页打开 Fix Alpha Border 然后重新导入。
怎么设 Godot 都切不匀这张图
它是紧凑图集,不是网格。在编辑器外面切成单张 PNG,再把它们拖进来。