3D瓦片地图采坑录

欢迎参与讨论,转载请注明出处。

前言

由于Demo的场景风格主打像素风格(这里的像素风格指具备一定精度的风格,而非时下流行的马赛克),故决定使用瓦片(Tile)地图来实现。也就是这种东西:
在这里插入图片描述
  游戏地图将由一个个规范化的单位图片拼接而成,是为瓦片。在早期的像素风格游戏可谓相当流行,因其构造成本低(无论从技术上还是美术上),而却能灵活拼接出各种各样的地图。于是我们也打算如此,但是在3D游戏下搞瓦片地图确是罕见得很。于是便开始了采坑之旅,遂成本文。

Sprytile

首先我们想到了在3D游戏下最接近瓦片地图思想的方案:Terrain,一般3D大地图都用类似方案:对一张平面地图进行各种揉捏形成地形,并在此之上涂抹各种图素。但可惜对于瓦片地图而言未免杀鸡用牛刀了,且在各方面都不能做到最适化,遂不考虑。
  其次便是Unity官方自带的2D Tilemap Editor,对瓦片方面的需求倒是满足了,可惜3D瓦片并不只是在一张平面上进行,而通过多张平面旋转组成场景未免勉强,遂放弃。
  既然在Unity这边行不通,那么便考虑生产端的Blender有什么合适的插件了。果不其然找到了Sprytile,一看就明白,就是它了:
在这里插入图片描述
  使用准备好的tile图集,划分格子,在Blender以格子为单位进行填涂,每个格子将会是一个面,支持XYZ三个平面进行,在填涂完成后可作为正常模型进行各种操作。一切看起来是那么的美好,然后一路到了游戏后……

过滤之殇

前篇的截图便可看出问题所在:
在这里插入图片描述
  可以看到地板之间存在奇怪的黑线:
在这里插入图片描述
  根据插件文档提供的Unity导出说明来看,必须要将地图贴图的过滤模式设置为Point,即邻近过滤:
在这里插入图片描述
  嗯,黑线果然消失了。那么问题便出在图片的过滤模式了,回去复习了下纹理过滤,答案昭然若揭:
在这里插入图片描述
  由于瓦片地图的习惯会将相关图素集成一块,形成连续的图块:
在这里插入图片描述
  那么在线性过滤下,图块的边缘像素在采样的时候将会混进相邻图块的颜色,于是那些奇怪的黑线便是这么来的。
  也许读者会认为:不用线性过滤不就得了,毕竟插件作者也是这么认为的。可惜我们做的风格并不适合用邻近过滤,那将显得与人物画风差异过大且马赛克:
在这里插入图片描述
  细心观察上图底部,这是开启抗锯齿(MSAA)导致的。查阅资料后发现这是MSAA的特点导致,如此哪怕我们想靠邻近过滤解决也是没门……当然也考虑过更换为其他抗锯齿的方式,但是效果都不甚喜人,于是开始寻觅解决之道。

无奈的解法

首先考虑对tile图片进行下手:既然边缘会采样到相邻图块的像素,那么将它们隔开不就得了,如此:
在这里插入图片描述
  当然这么做的话要让Sprytile有所支持才行,好在它是开源的。Blender的插件改起来也还算容易,毕竟会在界面提示标识好功能函数名。结果还是翻车了:
在这里插入图片描述
  瓦片之间出现了奇怪的透明点,仔细一想便明白了:透明像素一样会被采样到,所以会影响到透明度。于是迅速想到下个方案:让每个图块外扩边缘1像素,这样边缘的采样只会采样到相同颜色的像素:
在这里插入图片描述
  很不错,黑线什么的都消失了,哪怕是开着MSAA。同时美术也在Blender琢磨出了一种方法:在不做任何处理的贴图的基础上,将瓦片地图模型的UV全部缩小一点(参考值:0.96),如此便不会直接采样到边缘像素,从而以牺牲了一点点边缘效果解决了问题。
  两者的效果最终是差不多的,但都是不完美的,在编辑器里便一目了然:
在这里插入图片描述
  可以看得出,格子之间的边界可谓泾渭分明,这是因为每个格子都是独立的mesh,它们并不是作为一个整体去渲染,也就不存在视为一个整体去采样。也就无法达到真正意义上2D游戏里要达到的效果(格子之间彻底融为一体)。要这么做有两种方式:第一种是根据瓦片地图的填涂情况最终生成大贴图与新模型,但这种方式相当不优化,并且会急剧增大包体。其次是仿照以前的2D游戏做法:游戏本身使用邻近过滤渲染,最后将渲染成图进行拉伸放大(放大方式采用线性过滤),但这是牺牲画面分辨率带来的。
  经过以上总结可以看出,基本不存在非常完美的解决方案,只能矮子里拔大个了:UV缩小的方案从工序上最为简单,且显示效果也能接受(没对比过原版基本看不出太多异样)。

后记

一开始我们觉得这种瓦片地图1个格子就占2个三角形,面数会不会太高了。结果在参考其他游戏的情况时发现《闪之轨迹3》的一组垃圾桶的面数……
在这里插入图片描述
  嗯,一组垃圾桶的面数都完爆我整个瓦片地图模型了,法老控牛逼!
  顺带一提的是,刚才提到的格子边界问题在Unity官方的2D Tilemap Editor也是存在的,只能说是瓦片地图的局限性了,好在离得远也看不太出。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CATiledLayer 是一个可以用来加载和显示大尺寸瓦片地图的图层类。瓦片地图是一种将地图分割成许多小块(瓦片)并按需加载显示的技术。 CATiledLayer 在处理瓦片地图时具有很多优势。首先,它可以分割整个地图成许多小瓦片,这样只有在需要显示的时候才加载对应的瓦片,有效地节省了内存空间。其次,CATiledLayer 支持异步地加载瓦片,这意味着在瓦片加载过程中,用户仍然可以滑动和放大缩小地图而不会有明显的卡顿。此外,CATiledLayer 还可以自动处理瓦片的级别细节,即在放大和缩小地图时,会自动加载和卸载相应级别的瓦片,以提供更好的用户体验。 使用 CATiledLayer 加载瓦片地图的过程主要包括以下几个步骤。首先,我们需要将整个地图图片切割成许多小瓦片,并为每个瓦片创建一个对应的 CATiledLayer。然后,我们需要实现一个自定义的 UIView,并将其 layer 类型设置为 CATiledLayer。在自定义的 UIView 中,我们需要实现 drawRect 方法,在该方法中根据当前的可视区域,使用 CGContextDrawImage 方法将需要显示的瓦片绘制到屏幕上。此外,我们还需要实现一个自定义的 UIScrollView,用于处理地图的滑动和缩放,以及对应瓦片的加载和卸载。 总的来说,CATiledLayer 瓦片地图是一种高效加载和显示大尺寸地图的技术,它通过分割地图成小瓦片并按需加载显示,提供了更好的用户体验和内存效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值