场景贴图的分级策略

场景贴图的分级策略

这是第154篇UWA技术知识分享的推送。今天我们继续为大家精选了若干和开发、优化相关的问题,建议阅读时间10分钟,认真读完必有收获。

UWA 问答社区:answer.uwa4d.com
UWA QQ群2:793972859(原群已满员)


本期目录:

  • 关于场景贴图压缩的技巧
  • XLua读取游戏配置表格方式
  • AssetBundle加载烘焙场景,光照失效如何解决
  • OverDraw优化问题
  • 对应多个BMFont美术字体,如何优化到一个DrawCall里

Texture

Q:1、场景贴图在压缩格式时,是否能针对高中低端机型做区分?

2、如果不能,就意味着不管是什么配置的机型都会加载同样内存的场景贴图。那么问题就来了,压缩的厉害一些,在高配手机上效果又不太好,压的不那么厉害,在低配机上内存又很吃紧,这种情况下有什么好的解决办法吗?

3、另外有个不解的疑问,按理说一张2048x2048的贴图,在开启Mipmap的情况下,RGB24格式,内存应该是16MB(12MB的贴图+约3MB的Mipmap)。但是我打包到手机上,真机Profile时看到的这张图片,占用内存值是4MB!而当关了Mipmap时就正常了,显示的是16MB,难道真机Profile时得到的不是真正的内存占用而是显存上的占用?还是说这是Unity Profile的一个bug?

补充下:在UWA上测试,发现也是一样的情况,开了Mipmap后2048x2048的也是4MB。

请输入图片描述

A1:1、可以区分,代价就是包体会大,需要额外根据高低配设置,加载不同资源的代码逻辑。当然用小包根据当前的硬件来判断适合哪种资源,来进行下载也是目前常见的一种做法(不过国内完整包的做法还是比较多的)。

2、除了不同机器直接下载不同资源的方式,或者多套贴图都在包内的方法,没有什么好方式了吧?Unity的QualitySettings配置里的TextureQuality是一个可能可行的选项,我没有进行过内存对比,按照之前的理解,应该是基于Mipmap来节省显存的,这个题主可以自己测试下。不过这不是题主要的不同压缩格式的方式。

请输入图片描述

3、2048x2048的内存占用我暂时也没想到为什么,看看别的朋友的回复吧。不过题主你都用RGB24这种格式,不爆内存才怪啊。建议用对应目标设备上直接支持的压缩格式。高质量的压缩,尤其在3D场景下,除了Normal等特殊贴图,看不出明显差异的。
感谢贾伟昊@UWA问答社区提供了回答

A2:现在很多游戏都会根据机型进行适配,以现在大部分游戏对Android Top 300进行适配的标准ETC2可以作为标准压缩格式,iOS在考虑iPhone 5s的情况下需要PVRTC4,如果不考虑该机型可以用ASTC。

在标准包中我们只进行以上格式的压缩,但是在高配机型,我们可以让用户选择下载高清资源。这部分高清资源,我们可以通过修改图片压缩格式为ASTC,再重新打包AssetBundle,让用户自行进行下载,并且给一定的游戏道具奖励。

以上策略针对MMO等类型的重度大型游戏比较合适,如果是休闲或者轻度游戏,可以选择部分资源存在两份不同压缩格式里,根据机型加载不同资源。
感谢郑骁@UWA问答社区提供了回答

A3:你们的Unity版本是2018.3,很有可能是开了Texture Mipmap Steaming功能,由于内存Budget达到了设定上限,从而引擎只加载了Mipmap1~n层的内容。对于原图内存是12MB的问题,其Mipmap第一层后的总和就是4MB左右。所以,个人推测你的第三个问题是这样的。

该回答由UWA提供,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c9aea76419e740b2b8afb84


Lua

Q:我们项目接入XLua,主要想用来做UI逻辑编写和热更新。写UI逻辑时,需要在Lua脚本中读取游戏配置表格数据,网上查询了几种解决方案:
1、C#层提供查表接口给Lua用,感觉这种方式性能不太好;
2、将游戏Excel配置表通过工具转成Lua Table,直接在Lua侧使用,但现在没选好开源的工具;
3、其他方案。

希望各位大佬提供下具体项目经验,和对应开源工具的参考,方便后来开发的同学。

A1:针对方案2,分享下tabtoy excel导出器这个工具。它可以把Excel配置表转成Lua文件直接在Lua中使用。

代码实例:

-- 添加搜索路径
package.path = package.path .. ";../?.lua"

-- 加载
local t = require "Config"

-- 直接访问原始数据
print(t.Sample[1].Name)

-- 通过索引访问
print(t.SampleByID[103].ID)

print(t.SampleByName["黑猫警长"].ID)

感谢张锐@UWA问答社区提供了回答

A2:在GitHub上有很多Excel导出成Lua的工具,但本质大同小异,都需要对现有表格做一些规则修改和约束,具体还得看哪个更接近你项目的格式,然后自己做下适配。

我最早在14年初给自己项目做了个导出器,后来被不断改造,现在是XlsxToLua这个工具。

感谢厅级码农@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c95df0b276f530b35fdd953


Lightmap

Q:通过AssetBundle加载的场景发现无灯光效果。
问题1:发现static属性发生了改变,这个是否会影响和批。
问题2:发现Shadowmask没有引用到,这个准备按照处理LightmapLight方式处理,是否可行。
问题3:最重的如何通过AssetBundle加载的场景有光照信息。

测试发现,如果把整个场景打成一个AssetBundle是没有问题的,但是如果提取了公用资源,光照就会失效。

麻烦各位大佬有碰到过得帮忙回复一下,感谢!

图1是Unity里面的场景信息,图2是通过AssetBundle模拟加载出来的场景信息。


A1:几个问题总结一下:
1、Shader Variants丢失;
2、AssetBundle打包时优化掉了Lightmap;
3、Static只对Editor下放置在场景中的物体生效,Runtime时实例化不生效,并不会静态合批。

解决办法:
1、创建Shader Variants Collection,将使用到的Shader变种选择正确,打包时将Shader Variants Collection和使用到的Shader打包到同一个AssetBundle中,这样Shader的AssetBundle包可剥离场景。
2、Editor->Project Settings->Graphics->Shader Stripping 将Lightmap Modes改成Custom,再根据Lightmap烘焙模式选择对应模式 ,主要原因是Auto会根据你打AssetBundle时候打开的场景来设置这些选项,如果是空场景,没有Lightmap,就会优化掉Shader中Lightmap部分。
3、可以手动合并Mesh,减少DrawCall ,详见CombineInstance相关API。

感谢郑骁@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c9ba4cd419e740b2b8afbb2


OverDraw

Q:最近在做OverDraw的优化,由于我们的UI界面是窗口式,没有覆盖全屏,主相机一直在渲染。为了降低DrawCall和OverDraw,所以我们对主相机做了截屏,放在弹出的UI窗口后面,关闭了主相机,大大降低了打开UI界面时的DrawCall,这是方案A。但是因为是一整张的背景截图,中间有一大块是被UI挡住看不见的,所以我们又想把中间被UI挡住的部分挖掉,只留下看得见的部分,这样可以降低OverDraw,这是方案B。

现在问题来了,方案A比方案B低3个DrawCall,但是会多0.4x的OverDraw,我们项目CPU和GPU都没有遇到瓶颈,只考虑耗电量和温度,应该选哪个方案好呢?

A:首先需要说,A和B都是好方案!而且能进一步考虑到方案B,说明题主团队的自我要求和执行力都很高!

其次,如果方案A和B中,CPU和GPU都没有达到瓶颈,那么其实A和B都是没问题的,就看哪种做法的人力成本最少即可。但如果单一从计算力上来考量,个人推荐方案B,因为3个DrawCall的增加几乎可以忽略不计,但是0.4x的OverDraw还是一个不可忽略的开销。

该回答由UWA提供,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c9c3e7a276f530b35fdda51


UI

Q:游戏内多种战斗飘字效果,对应多个BMFont美术字体,如何优化到一个DrawCall里?各种类型的伤害及来源都有不同的飘字效果,比如暴击、中毒、闪避、回血等等,之前的方案是使用BMFont制作多种字体,对应生成UGUI里的自定义字体。这样带来的问题是,各种飘字同时穿插着出现时,UI合批被打断,产生了很多DrawCall。

一个优化方案是将不同的美术字体放到不同的层里,有多少种字体则最多产生多少个DrawCall,但这个方案会出现明显的问题就是某一类伤害会被另一类全部遮挡, 而策划期望的效果是不同类型的飘字效果之间可以相互穿插。

目前想到的方案是将所有的美术字体制作成一个BMFont字体文件,对于不同类型的伤害数字,使用分组的ASCII码去访问同一个number的不同表现。

想请问下大家在用的方案?

A:我会选择“将所有的美术字体制作成一个BMFont字体文件”,对不同数字就用其他字符代替转换一下就好啦。不过要注意不同美术字下字号统一之类的问题,不过这都是好解决的。

而且建议题主考虑将“暴击”、“中毒”这种一个词作为一个字来处理,对应的字符可以选一个特定的约定好的。这样的好处是,如果之后做泰文、英文版的美术字很可能都是连在一起,一个词作为一个整体,可以统一对应的字符。

感谢hcj@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/5c98c763276f530b35fdd96c


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(原群已满员)

封面图来源于网络