ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Aseprite与Unity瓦片地图:从像素画到Tilemap的完整流程

Aseprite与Unity瓦片地图:从像素画到Tilemap的完整流程 做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 像素比和PPUUnity里的第一个大坑Unity导入图片时有个属性叫Pixels Per UnitPPU默认值是100。如果你的瓦片是32×32像素PPU为100的话它在Unity里占据的世界单位是0.32——这在你设置摄像机大小Camera Size时很容易算错导致画面看起来忽大忽小。我的建议是把PPU设为16或32和你的瓦片像素尺寸保持一致如果PPU3232px的瓦片正好占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 TypeSprite (2D and UI)。Sprite ModeMultiple。因为图集里有多块瓦片必须是Multiple才能切割。Pixels Per Unit32或者和瓦片尺寸一致。Filter ModePoint (no filter)。CompressionNone。Alpha Is Transparency勾选如果不勾透明区域会显示为白色或黑色方块。设置完点击Apply然后打开Sprite Editor。在Sprite Editor里选择SliceType选Grid by Cell SizePixel 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 PaletteUnity会认为你只有一个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分钟它对保持工作流效率和手感的作用很大。
返回列表