☰
Aseprite与Unity瓦片地图:从像素画到Tilemap的完整流程
2026/10/4 2:03:38 网站建设 项目流程

做2D平台游戏的人,应该都绕不开瓦片地图这件事。早几年我还在用Photoshop一格一格拼素材,然后手动对齐到Unity里,那叫一个折磨。后来换成Aseprite配合Unity的Tile Palette工作流,效率直接翻了一倍还不止。这篇就把我这几年用Aseprite做Unity 2D平台游戏瓦片素材的完整思路、配置参数和踩坑记录整理出来,希望对正在自己动手做游戏素材的朋友有所帮助。

这套流程适合谁?如果你会用Aseprite画像素画,但对Unity的瓦片地图系统还不太熟;或者你已经在Unity里摸过Tilemap,但总觉得素材尺寸对不上、碰撞体乱跑、刷地图时边缘缝合有问题——那这篇文章正好是给你准备的。我会从画布怎么设、瓦片怎么画、导出怎么配,一直讲到Unity里怎么导入、怎么刷地图、碰撞体怎么调,一条龙全走完。

1. 整体设计思路:为什么用Aseprite配合Unity Tilemap

先说个最核心的概念:瓦片地图本质上就是“用小块素材拼大场景”。所以你第一步要想的不是“怎么画”,而是“画多大多小的块”。Unity的Tilemap系统本身并不限制瓦片尺寸,但Aseprite和Unity都有个像素单位的概念,两边对不上,出来的东西要么糊,要么边缘有白线。

我个人的习惯是:平台游戏素材统一用16×16或32×32的瓦片基准,角色按高度32px或64px来画。这个尺寸在Aseprite里画细节不会太憋屈,在Unity里做物理碰撞体也不会因为瓦片太小导致性能吃紧。

选Aseprite而不是Photoshop或Procreate,原因其实很实在:

  • Aseprite是像素画专用工具,自带网格、对称画笔、阴影替换,画瓦片的效率比通用绘图软件高得多。
  • 它有专门的Tile模式(Tile Mode),可以在绘制时预览瓦片在平铺状态下的接缝效果,这个功能做瓦片素材几乎是刚需。
  • 导出成Sprite Sheet非常方便,并且支持按图层、按帧导出,处理Unity需要的透明背景PNG很简单。

设计思路上,做平台游戏的瓦片素材与做俯视角RPG有个很大的区别:平台游戏的地形是有“厚度”和“深度”的。地面不能只是一层薄薄的草皮,它需要顶面、侧面的厚度感、底部的阴影,这样刷出来的平台才有体积感。所以在Aseprite里画一块地面瓦片时,我通常会预留大概4~6px的高度来做厚度和阴影,而不是把像素占满整块瓦片。这个细节直接影响最终场景的视觉质量。

另外,一个常见的误区是“一块瓦片就画一个完整图案”。实际上平台游戏里,地面通常需要拆成多种瓦片来组合:顶部边缘、中间填充、左侧边缘、右侧边缘、独立浮空岛、斜坡、内部实心块等。我一般在Aseprite里新建一个文件,里面通过图层分组来区分这些变体,然后统一导出成一张Sprite Sheet。这样在Unity里建Palette时就可以一次把整组瓦片拖进去,不用来回切换文件。

这里还要说一句题外话:如果你手头没Aseprite,用Photoshop配合网格也能做,但Tile模式的实时预览没有平替方案,做瓦片时反复“测试平铺效果”的效率差别非常大。Aseprite是付费软件但价格不高,Steam上经常打折,我个人认为是做2D素材最值得的投资之一。

2. 核心细节解析与实操要点

2.1 画布尺寸与网格设置

打开Aseprite新建文件时,我建议直接把尺寸设为你要的瓦片图集大小。比如你打算做32×32的瓦片,一套地形包含16块变体,那画布可以设为128×128,或者直接用4×4的网格排列。

这里有一个Aseprite的关键设置:View → Grid Settings。网格必须设置为跟瓦片一样的大小(32×32),并且开启Snap to Grid。这样你画线、画矩形时就会自动贴齐瓦片边界,不会出现某个像素超出范围的问题。

更关键的是,Aseprite的网格显示默认是Pixel Grid,在缩放级别小于等于400%时像素网格不会显示。很多人因此以为没开成功——其实你要看的是Tile Grid,这个才是对应瓦片边界的网格。在View菜单里勾选Show Tile Grid,它会在画布上以蓝色虚线标出每个瓦片的分界,配合Tile Mode使用,效果一目了然。

2.2 Tile Mode平铺预览的正确用法

进入View → Tile Mode,有三个选项:None、Tilemap、Tilemap (30°)等。做平台游戏我几乎只用Tilemap,它会让Aseprite的画布在水平、垂直方向上同时无限平铺。这样当你绘制左右会相接的瓦片时,画面边缘会连续显示相邻瓦片的延伸部分,你就能实时看到接缝是否对齐。

使用技巧上,我会在画完地面瓦片的主体后,开启Tile Mode检查左右边缘的像素连续性。比如画一个草地顶部边缘瓦片,左右两侧如果有明显的断点,就说明草叶轮廓没画好,调整一下边缘像素即可。

需要特别注意的是:在Tile Mode下,如果你用了“填满整个画布”的矩形工具,视觉上很爽,但画出来的内容可能超出了单个瓦片边界。这在后面做Sprite Sheet切割时会出大问题——Unity会把它当成多块瓦片的组合,而不是一块完整的瓦片。所以我的建议是:要么在单瓦片画布上画,画完再复制成图集;要么在图集里时严格按Grid对齐来画,不要画跨格内容。

2.3 图层规范:把碰撞体区域画出来

用Aseprite做瓦片素材,除了画“看得见”的颜色层之外,我还会额外建一个“碰撞层”或“实体层”,用纯色块(比如亮红色)标记哪些区域是实心碰撞体。这样在Unity里生成瓦片碰撞体的时候,可以很直观地对齐。

具体做法:每个瓦片文件里,在最底层放一个颜色层用于绘制碰撞范围。注意这个碰撞层在导出前要隐藏,不然红色块会出现在最终素材里。为了便于识别,我给碰撞层命名时都带“_collision”后缀,配合Aseprite的图层颜色标签功能,一眼就能看出来哪层是干嘛的。

这招在做复杂地形时特别有用。例如浮空岛瓦片,视觉上它是一个带底部钟乳石的土块,但实际碰撞区域只需要覆盖顶部平面和两侧,底下的钟乳石凸起不应该阻挡角色。你把碰撞区域画成矩形块,导出后在Unity里通过Sprite Editor修改Sprite的Custom Physics Shape,就能做出“看起来厚实、站上去只有顶面有碰撞”的效果。

2.4 像素比和PPU:Unity里的第一个大坑

Unity导入图片时有个属性叫Pixels Per Unit(PPU),默认值是100。如果你的瓦片是32×32像素,PPU为100的话,它在Unity里占据的世界单位是0.32——这在你设置摄像机大小(Camera Size)时很容易算错,导致画面看起来忽大忽小。

我的建议是把PPU设为16或32,和你的瓦片像素尺寸保持一致(如果PPU=32,32px的瓦片正好占1个Unity单位)。这样设计关卡时,说“这块平台长3格”就是“3米”,换算和调整都方便。也建议把Unity项目里的Pixel Perfect Camera插件用起来,它可以直接让镜头像素对齐,彻底避免像素发虚。

如果你不想用Pixel Perfect Camera,至少要把Sprite的Filter Mode改成Point (no filter),Compression改成None,这样才能保证像素边缘锐利不发糊。这两个选项在Unity的Import Settings里,很多人忘了改,结果素材看着像隔了一层雾。

3. 实操过程:从Aseprite到Unity的完整流程

3.1 在Aseprite里制作第一套瓦片

我以32×32瓦片、做一套“草地+泥土”地形举例。新建文件,尺寸定为128×128,也就是4×4个瓦片。第一格画草地顶部(上面是草,下面是泥土);第二格画纯泥土填充;第三格画草地左侧边缘;第四格画草地右侧边缘;第二行可以画左侧转角、右侧转角、独立土块、背景装饰物等等。这个排列方式没有绝对标准,自己记住位置就行。

画的过程中我习惯把参照层打开——在Layer面板新建一个空图层,用1px描边画出32×32的格子,放在最顶层并设为半透明。这样做的好处是每块瓦片的边界始终可见,不会画着画着就跑偏。

画完一个瓦片后,用Rectangular Marquee选中该区域,复制一份放到另一个测试文件里开启Tile Mode预览。如果边缘有瑕疵就回到原文件修。这个过程看起来麻烦,实际上是最省时间的方法,因为等进入Unity刷地图时才发现瓦片边缘对不上,返工成本远高于此。

3.2 导出Sprite Sheet的正确设置

在Aseprite里,File → Export Sprite Sheet是导出图集的关键入口。关键设置如下:

  • Sheet Type:选择By Rows或By Columns,取决于你的瓦片排列方向。我习惯按行排列,方便在Unity里按顺序剪切。
  • Size:可以手动设成128×128,保持原图尺寸。
  • Layers:选择Visible Layers,但要确保碰撞层已被隐藏。
  • Borders:**这里要注意——如果瓦片之间需要留边距,或者你希望每帧之间有边界,就把Border设为0。**Aseprite默认会在每个瓦片周围加一条1px的边框,这个边框会被Unity读成透明边距,看似无害,但实际会导致瓦片在Sprite Editor的九宫格切割中多出1px错误。我在第一次做时就因为这个问题,花了很久才查明白为什么瓦片总是对不准格线。

导出格式选PNG,背景透明。文件名建议用项目相关命名,比如grassland_tileset.png,避免中文和空格。

Aseprite也可以导出JSON数据文件(包含每个瓦片的位置信息)。这个文件后面在Unity里其实用不上,因为Tile Palette不需要外部映射数据;但如果你想通过脚本来加载图集,JSON就有用了。平台游戏通常不用这么复杂,知道有这功能就行。

3.3 Unity导入设置:一步都不能少

把导出的PNG拖进Unity工程后,选中它,在Inspector里调如下参数:

  • Texture Type:Sprite (2D and UI)。
  • Sprite Mode:Multiple。因为图集里有多块瓦片,必须是Multiple才能切割。
  • Pixels Per Unit:32(或者和瓦片尺寸一致)。
  • Filter Mode:Point (no filter)。
  • Compression:None。
  • Alpha Is Transparency:勾选(如果不勾,透明区域会显示为白色或黑色方块)。

设置完点击Apply,然后打开Sprite Editor。在Sprite Editor里选择Slice,Type选Grid by Cell Size,Pixel Size填32×32。点击Slice按钮后,图集就会按格子自动切成16块独立Sprite。

这里有个容易踩的坑:如果你的图集里某一块瓦片是空的(比如你留了个空位),Unity也能切出来,但那个Sprite会是全透明。用的时候最好手动删掉,否则刷地图时很难选到它上面的有效瓦片。

3.4 搭建Tile Palette并刷出第一张地图

Unity里Window → 2D → Tile Palette,打开面板后会要求新建Palette,命名后会自动生成一个文件夹。然后把你切割好的Sprite整体拖入Tile Palette窗口,Unity会提示自动生成对应的Tile资源。

之后做的事情就很简单了:在Tile Palette里选中需要的瓦片,在场景中用Tilemap画笔工具刷到地图上。

但我注意到一个新手常遇到的问题:用画笔刷出来的地面,总是有细缝或闪线。这通常是因为瓦片之间的边缘有半透明像素或者颜色溢出。解决办法一般有两个:

  • 在Aseprite绘制时,用Sprite → Outline给瓦片描一圈边,或者在边缘处让像素充分覆盖。
  • 在Unity里打开Tilemap的渲染设置,勾选Use Edge Collider之类的东西(但更根本的方法是改素材边缘)。

更保险的方案:在Aseprite里做瓦片时,在四周各多画1~2个像素的“出血边”,内容与对面边缘相延续(即右侧边缘的内容延续到左侧边缘外1px)。这样即使Unity做了一些边缘平滑处理,也不会露出底色缝隙。

3.5 为平台游戏添加碰撞体

Unity Tilemap添加碰撞体的方式有两种:

  • 给Tilemap对象挂Tilemap Collider 2D:它会为每个瓦片自动生成独立碰撞体。瓦片多时会生成很多小的碰撞体,性能并不好。
  • 再挂一个Composite Collider 2D,并把Tilemap Collider 2D的Used By Composite勾选上。这样Unity会自动合并所有瓦片的碰撞区域,大大减少物理计算量。

平台游戏的平台碰撞还有个细节:角色起跳时,有时候会卡在平台侧面。解决思路是尽量用“底部只有薄层碰撞”的地形——即碰撞体区域只占瓦片的上部几px,下面留空。这样角色无论从下方还是侧方碰到平台,都不会被平台边缘“顶住”。

实现方法是在Unity的Sprite Editor里,为每个瓦片手动编辑Custom Physics Shape。选中一个Sprite,在Sprite Editor里开启Custom Physics Shape编辑模式,然后用网格拖拽出你想要的碰撞体轮廓。这个轮廓不需要和瓦片像素完全一致,简单矩形、梯形甚至任意多边形都可以。比如一块带钟乳石的土块瓦片,你把碰撞轮廓只画在土块的矩形区域,这样钟乳石就只是装饰,不参与碰撞。

不过如果瓦片数量多,逐个手动编辑会有点繁琐。更高效的做法是:在设计阶段就控制瓦片的碰撞区域——把视觉内容统一画在有规律的范围内,然后通过一个脚本来批量生成瓦片资源的Collider Type,或者接受默认碰撞,再用Composite Collider合并后整体微调。

4. 常见问题与排查技巧实录

4.1 瓦片颜色发灰或发白

这种情况九成是Unity导入设置里Compression用了默认的Normal Quality,导致PNG的透明边缘产生了偏移,颜色变得怪怪的。另一个原因是图集用了非Point的Filter Mode,像素被平滑后透明区域边缘混入了白色。检查并改为None压缩 +Point过滤即可。

4.2 刷出来的地图有明显网格线

网格线问题的本质是瓦片边缘像素没对齐或半透明。排查思路:先在Aseprite里确认瓦片内容没有溢出、边缘像素是清晰的实色;再确认Unity导入时PPU和像素尺寸对应;最后在Tile Palette的瓦片资源上,看Sprite是否被正确切割,有没有附带透明边距。

还有一个很容易忽略的点:如果Aseprite导出Sprite Sheet时设置了Border Padding,那么瓦片之间会插入透明像素,Unity在切割时如果按Grid by Cell Size切,就会把Padding也算进格子,导致部分内容被裁掉或错位。我建议导出时Padding一律设0,不要给瓦片间加边距。

4.3 在Tile Palette里选不到想要的瓦片

常发生在Sprite Mode没有设为Multiple的情况下。如果你只拖了一张整图进Tile Palette,Unity会认为你只有一个Sprite,自然没法按格子选。解决办法是回到Texture Import Settings里把Sprite Mode改为Multiple并进行切片,再重新拖入Tile Palette。

如果你已经在Sprite Editor里切好片,拖入后仍然只有一个Tile,那我猜是你操作时拖的是原始Texture而不是Sprite。需要在项目窗口里展开这个Texture的子资源(点开左边的小箭头),把切片后的Sprite批量选中再拖入Tile Palette。

4.4 碰撞体比看到的像素大或小

这是Custom Physics Shape没有调整导致的。Unity默认会用Sprite的不透明像素边界自动生成Physics Shape,如果你为了视觉效果把某些像素做得很淡(低透明度),Unity可能不把淡色像素算进碰撞,导致碰撞体比视觉小。

解决办法是在Sprite Editor里手动调整Physics Shape,或者用规则形状(矩形)覆盖碰撞区域。我个人建议,不太复杂的瓦片统一用Rectangular Collider,复杂的平台再单独调Custom Physics Shape。这样既有性能又有精度。

4.5 切换场景时瓦片闪烁

这个问题经常出现在大量瓦片同时渲染时。原因多是Z-fighting——Tilemap的多个Layer叠加时,相邻图层在深度上存在微小穿插。解决办法是检查各Tilemap Layer的Order in Layer设置,确保它们之间的深度差足够;另外,确保摄像机没有开太近的近裁剪面,也能减少闪烁。

4.6 导出后瓦片出现重复黑影

如果瓦片本身画了阴影,导出后场景里出现两块阴影或者奇怪的墨团,大概率是你把含有阴影的装饰物做成了独立瓦片,同时又铺了一层地面阴影图层。检查一下Tilemap的层级结构,做好“地形层”“装饰层”“背景层”的区分,阴影放在装饰层或独立阴影层,不要混在地形层里重复叠加。

5. 平台游戏瓦片素材的进阶经验

做完第一套可以用的瓦片后,你很快会不满足于“平地面+土块”的玩法。这里分享几个我后来摸索出来的进阶技巧,适合想在平台游戏里做出更多变化的开发者。

5.1 用“空Tile挖洞法”打造立体感

我们常看到那些优秀的平台游戏,地面并不是一整块实心平面,而是有断崖、有层次、有洞穴入口。实现这些效果,不需要很多额外瓦片——把地形层挖空几格,再在挖空处贴上背景层瓦片,视觉层次立刻就有了。

具体操作上,我习惯把同一个区域拆成三个Tilemap Layer:背景层(Back)、地形层(Ground)、前景装饰层(Front)。地形层挖掉的格子,背景层露出的是远景山体,前景层可以挂几片叶子做遮挡。这样做出来的场景有呼吸感,不会像一面墙一样闷。

空Tile挖洞法的好处是复用性强,不需要为了每个洞口专门画一套新瓦片。只要把背景爬山虎、洞口上沿等装饰素材准备好,组合起来变化就非常丰富。

5.2 活用Aseprite的调色板替换和阴影替换

Aseprite里有一个很实用的功能:Color → Replace Color或使用调色板(Palette)批量替换颜色。当你画完一套草地瓦片后,想再出一套“荒漠版”或“雪地版”,完全不需要重画,只需要把调色板里的绿色系整体替换成黄沙色或白色系,再顺手改一下细节线条。配合Aseprite的Remap Palette对话框,可以按原颜色和目标颜色的映射关系一次替换多组颜色,效率极高。

做雪地版本时,我通常还会顺手加一层高光白色在草叶顶部和边缘,因为纯替换颜色会让画面缺少“积雪感”。这个小步骤在Aseprite里就是加一层白色像素画画的事,但视觉差异很大。

5.3 用Aseprite的脚本批量生成变体

如果你用的瓦片数量特别多,可以试试Aseprite的Lua脚本功能。比如写一个简单脚本,将当前选中的图层所有像素做水平翻转/垂直翻转,并生成新的瓦片,复制到当前文件的空白区域。这样一套瓦片就能翻出好几个方向变体,省下不少重复绘制的时间。

不过需要提醒的是,翻转生成的瓦片有时候会出现光影方向错误。比如左侧高光翻转后变成右侧高光,场景里光源方向就对不上了。我自己更推荐手动微调翻转后的阴影层,不要完全依赖脚本。比如草地的光照阴影方向,我都是在原图上画好,然后手动调整每个方向变体的阴影位置,虽然费点功夫,但出来的光影是一致的。

5.4 用Tilemap的Rule Tile自动填充地形

Unity本身支持Rule Tile,它可以让你设置规则——当某块瓦片旁边有相同瓦片时,自动切换为对应的边缘变体。用Rule Tile之后,你只需要画一条地形轮廓,其他部分Unity会自动帮你填充成无缝的草地/泥土过渡。

但Rule Tile有个前提:你的瓦片素材必须按照特定命名规则排列,比如grass_top、grass_left、grass_inner_corner等。在Aseprite里画的时候,建议大家提前规划好命名,或者回到Unity里逐个指定Sprite。这个初始化过程略麻烦,但一旦配好,后续刷地图是真的省心。

我个人是在做一个demo时开始用Rule Tile的。前几个小时花得很痛苦,但之后就体验到了“画一条线自动生成整面地形墙”的快感,效率提升非常明显。如果你打算长期做某个项目,强烈建议学一下Rule Tile的配置方式,官方文档和很多教程都有讲解,这里不展开。

6. 性能与工程质量:别让瓦片成为性能黑洞

很多新手做瓦片地图,刷得很开心,到了真机上却卡成PPT。虽然平台游戏的瓦片数量不一定多到爆炸,但性能问题还是要提前重视。

Tilemap的优势在于,Unity本身会合并同一Tilemap Layer上相邻瓦片的网格,所以瓦片本身引起的Draw Call并不会像挂很多独立Sprite那样爆炸。真正影响性能的是:

  • 碰撞体数量过多且没有合并。
  • 大量复杂装饰瓦片挂在前景层,产生了过多的透明混合。
  • 摄像机范围内同时渲染了太多不需要显示的背景层。

所以我对平台游戏的瓦片规划建议如下:

  • 地形层和碰撞层尽量保持小而规整的瓦片数量,用Composite Collider合并碰撞区域。
  • 装饰层不要塞满整个场景,尤其是带透明渐变或粒子效果的装饰,宁可少放也不要铺满。
  • 远景背景不要放在Tilemap里。我习惯用独立的Sprite或者Parallax Layer来做远景,因为远景瓦片不需要碰撞,也不需要精确对齐,放Tilemap里反而浪费性能。

另外提醒一点,Unity的Tilemap材质默认是不参与动态合批的,所以如果你有大量动态物体频繁和Tilemap交错渲染,可以考虑为Tilemap设置单独的Sorting Layer,把动态角色放到最上层,避免混合排序时产生额外开销。

关于内存,也顺带提一句:同样的图集如果被反复引用,Unity会缓存多份Texture,不要在一个项目里放好几个相同内容的PNG副本。我发生过一件事:为了试配色,把一套草地瓦片复制了四五个文件,结果内存直接吃掉了上百MB,最后排查了半天才发现是重复贴图还没被引用时才释放。

如果你担心一些瓦片素材根本用不上,可以利用Unity的Addressables或简单的手动管理方式,把瓦片图集拆分成小图集:地形一套、装饰一套、背景一套。这样进入不同关卡时只加载对应图集,加载速度和内存表现都会好很多。

写到这里,我把自己这几年用Aseprite做Unity 2D平台游戏瓦片素材的方法论、步骤和避坑经验都整理出来了。核心就几条:画布尺寸和PPU对齐、导出不要加边距、Unity导入设置要正确、碰撞区域用心设计、图层规划前置。这几条做到位,后面的刷图过程会非常愉快。

最后再分享一个我自己一直保留的小习惯:每次新建一个2D项目,我会先花15分钟建一个_Templates文件夹,里面放好Aseprite的瓦片模板文件(16×16和32×32各一份),模板中已经包含了网格设置、碰撞层命名、图层颜色标签和自动导出配置。这样每次开新项目,第一步就直接进入画素材状态,而不是重新设置一遍。别小看这15分钟,它对保持工作流效率和手感的作用很大。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询