【内存优化】图集整理策略

微信公众号:游戏内圈
关注可了解更多游戏的教程及技巧。问题或建议,请公众号留言;


 

1. Sprite Packer介绍

Sprite Packer会把相同Packing Tag以及相同压缩格式的资源打到相同的图集里面。

所以影响图集大小主要集中在2个方面:

1:Packing Tag:图集名称
2:资源的压缩格式(format):安卓使用ETC1压缩,IOS默认使用PVRTC,选用不用压缩模式的2张图,即使是同一个Packing Tag,也会被打到2张不同的图集里面。

 

图集整理策略

知道了Sprite Packer怎么打包图集的,我们就要根据项目实际情况,去合理安排和整理图片资源,图集太大不行,太空也不行,然后又要关心业务,很多注意事项。

  1. 尽量紧凑,没有太多空白。比如一个图集512x512刚好塞满,现在额外加一张小图进去,就被迫变成512x1024,浪费的空间就很多了,而且在有的平台,该图集会被强制变成1024*1024,内存消耗从1M变成4M。
  2. Draw Call尽量少,同一个界面的小图尽量在一个图集里。
  3. 内存管理方便,加载性能好,打开一个界面时只加载必要的图集,关闭时可以方便地释放图集。
  4. AssetBundle打包\热更粒度合理,不能出现“热更一个新界面,大量图集都需要热更”的情况。
  5. 维护方便,当界面变化时,调整方便,包括生成图集、调整引用、新图集尺寸变化的影响、新图集AssetBundle变化的影响等等。
  6. 图集间隙尽量少,主要靠图集工具,常见的比如更紧凑的多边形Mesh替代Rect Mesh、旋转、切割等等。【TP比Unity的 Spirte Packer算法更好,这里我们不讨论】

我们现在项目的图集整理策略:

1:【脚本】按业务功能的预制,寻找依赖,收集所有预制引用的图片,
2:【脚本】将依赖的图片分别移动到对应业务命名的文件夹下【没有就创建】,如果有多个预制使用了同一张图片,我们就把它扔到common文件夹;
3:【人工】打开Spirte Packer,查看图集情况是否合理,合并零碎文件夹,让图集尽量紧凑,没有太多空白,尽量让图集处于2的n次方大小。【这个有大神能提供思路写个脚本吗?】
4:细碎图片扔进common。
5:程序来管理图集,就导致出包前,老是要要求美术缩小图片啊,调整目录啊,美术也不高兴,我觉得应该将这件事交给美术去做,拉美术一个人负责这件事,这样,他们上传的时候就会注意图片的通道RGBA啊,然后图集分配是否合理这些事,这样我们检查后的反馈就会少很多,大家合作也更舒服。

Unity上手动查看这些打包的大图方式:

1:打开 Sprite Packer界面【Window-Sprite Packer(2018版本:Window-2D-Sprite Packer)】
2:点击pack按钮【前提是已经设置了图片的Tag】

资源优化

纹理优化

纹理优化的目的是让它们占用的内存尽量的小,那么纹理加载进内存后,大小计算公式如下:

纹理内存大小(字节) = 纹理宽度 x 纹理高度 x 像素字节
像素字节 = 像素通道数(R/G/B/A) x 通道大小(1字节/半字节)

纹理尺寸

根据项目实际情况将贴图都缩小至合适的大小。这里的合适大小是指渲染对象在画面中大多数情况下不可能达到的最大尺寸,这个尺寸最好保持2的N次方。

纹理通道

通道优化的目的是降低像素所占的大小,可以通过以下方法达到目的:

*去除Alpha通道。可以减少通道数量,适用于不需要Alpha混合或Alpha Test的角色和物件
*应用单通道图。也可以减少通道数量,比如灰度图、地形高度图,掩码图,Shader掩码图等
*使用16位代替32位图。例如RGB444/RGBA4444就可以减少像素通道大小。

提高纹理复用率

*建立共享图库。将通用的元素放至共享库,例如按钮/进度条/背景/UI通用元素等。
*用九宫格图代替大块背景图。九宫格在游戏开发中是比较常见的UI组件。
*纹理元素通过变换可组合成复合纹理。例下图,上下左右对称的背景图可以用4张相同贴图实例通过旋转/翻转后获得。【mirror】

UI图集

界面A引用界面A图集和共享图集是允许的,但尽量不要引用界面B等其它图集。

但实际在游戏开发过程中,很难保证美术做到这一点,通常存在以下问题:

  1. 如果界面A确实要用到界面B图集的某个元素,怎么办?

参考解决方法:要看被引用元素的通用度,如果只是界面A和B在用,可以将被引用元素拷贝到界面A图集下;如果其它界面也会引用到,就可以将它移到共享图库。

  1. 有些UI纹理很大且很多界面都有用到,如果放在共享图库会导致共享图库急剧膨胀,怎么办?

参考解决方法:大尺寸纹理建议用九宫格+细节图,或通过组合的方式来代替。

  1. 如何保证美术制作的UI只引用到自身图集和共享图集?

参考解决方法:实现批处理检查工具,找出每个UI界面引用到的图集列表,引用的图集超过2个便是不合格。

拓展

1. 几种主流贴图压缩算法的实现原理详解

1.1 ETC

ETC压缩算法采用将图像中的chromatic和luminance分开存储的方式,
而在解码时使用luminance对chromatic进行调制进而重现原始图像信息。
ETC也主要有两种方法:ETC1和改进后的ETC2。
ETC1:

采用4x2的block进行分割(原始为4224=192,压缩后为32,压缩率为6):

ETC2:

根据ETC1的实现方式,如果其块内的颜色分布不均匀的话,则其存储的两个basecolor会较远的分布于插值趋线的较远的两侧,进行解压后会得到较低的压缩质量,因而ETC2就是解决如何针对这些较为特殊的颜色分布来选择更加优化的压缩策略。

1. 2. PVRTC

PVRTC的不是基于block的方式生成的,但是却也可以理解为以block方式组织的。

1.3 ASTC

ASTC中ARM研发的一种较新的贴图压缩格式,相对于上述几种方法具有较多的优势,其应该会慢慢成为之后移动设备上贴图压缩的主要标准和主流。其主要具有如下的特性:

1:较高的灵活性;
2:可变的压缩率;
3:支持2d/3d贴图;
4:适用于移动平台;
5:支持LDR/HDR贴图内容;
ASTC同样是基于block的压缩方式,但块的大小却较支持多种尺寸,比如从基本的4x4到12x12,而且块的宽高也不限于pot,比如6x5;每个块内的内容用128bits来进行存储,因而不同的块就对应着不同的压缩率。

参考:
UGUI 图集打包工具Sprite Packer
如何生成被4整除的NPOT图集,如何选择一个好的图集划分策略?
移动游戏性能优化通用技法 - 0向往0 - 博客园

posted @   Earui  阅读(156)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示