4

游戏项目中如何制定资源管理与加载策略

 2 years ago
source link: https://blog.uwa4d.com/archives/TechSharing_267.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

1)游戏项目中如何制定资源管理与加载策略
​2)对于热更新包体大小的最佳实践
3)URP某些Shader资源多次出现
4)关于手机发热问题如何入手
5)如何优化Delegate.Add/Remove这类堆内存的分配

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

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

Addressable

Q:第一个问题:现在Addressable的使用情况怎么样?使用类似Xassets一类的插件用于资源管理怎么样?

第二个问题:游戏启动的时候,热更资源,资源文件下载是以散文件的方式一个个下载好,还是打成一个整包下载好?

第三个问题:以前我们把AssetBundle包打到安装包内,然后安装完之后第1次启动时要把AssetBundle包解压到外面文件夹。这么做的好处就是统一维护一个外部资源目录,加载资源时不需要先判断外面目录再判断里面,然后根据资源在哪个目录写两种不同的加载方式。但是如果解压到外面,安装完之后整个游戏会增大很多。听说加载包内的资源比加载包外的更快,所以想问一下有没有必要再做解压这一个步骤?

A1:回答如下:

1.现在不太建议使用原生Addressable,因为在目前看到的一些项目中,冗余问题依然存在,而且无论是加载还是内存,问题都很多。加载的效率并不高,一旦做错,还会造成更差的问题,容错率比较低。

现在的大型团队基本上都在自己写这套系统了,便于查找原因。加载这块属于一个游戏的骨架(龙骨),不出问题没人注意,一出问题就有可能是致命的。

2.Xasset没做过调研不太清楚。

3.打成一个整包的,然后做差异化包,版本跨度越大,差异包越多,大文件下载也要考虑到断点续传的问题和多线程下载。要做很多处理,可能要接一个小插件,做加速、做断点续传、做多线程等,容易出问题。

散文件、颗粒度比较小,每次更新就更新几个文件,不用生成差异包。大版本更新就会下很多文件,但是不用考虑它的断点续传,因为文件比较小。还有一个好处就是同时可以起多条链接下载,安卓目前取消了链接数量上限,但是IO会很多。

4.没有必要解压,它在包内StreamingAssets下也是非压缩的,所以加载效率没问题。

该回答由UWA提供

A2:冗余问题, 估计他们是没有用Analyze工具分析冗余,我做过实验用Analyze工具分析解决冗余后,把生成后的Bundle提交到UWA的资源检查,分析得到的结果符合预期,没有意外的冗余问题,基本检查出的冗余,只要你用工具解决了,分析后冗余就不存在了。

感谢在路上哈哈@UWA问答社区提供了回答

A3:稍微补充一下:
1.Addressable针对做分包(核心包、可选包等)支持并不好,虽然有Catalog的分别下载更新,但是制作层面却没有很好支持。异步加载流程不能被Cancel掉,一旦发起必须走完,最后说这个资源不要了。它算是一项可选的比较通用的解决方案,但还是太通用和初级,一些中小型项目还是可以用的。但是项目一旦做复杂点,需求多了就可能应付不了。当然这也是Unity团队无法面面俱到、对应齐全的。一种思路是前期使用它,然后需要安排人深入理解和掌握,到项目中后期出现需求的时候动手改,毕竟代码都有。相对自己从0开始做一套系统还是有优势的。

2.下载环节还是建议考虑合包下载,毕竟不停开关N个HTTP连接消耗也是不少的,尤其当下载的粒度太细,Patch本身Size很小的情况下,会发现下载速度上不去。可以考虑客户端处理上还是小文件,但服务器端将相关Patch整理在一起合进大文件,然后利用HTTP的Range下载模式来定位下载这个大文件中一部分连续数据,这样减少HTTP连接数,提高下载效率。

3.读取在StreamingAssets内的AssetBundle文件不大,引擎自己搞定,但是读取非AssetBundle的资源,在Android平台下需要自行处理一下,无法用File.Open的形式打开,需要接入NDK的AAssetManager接口来访问。

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


AssetBundle

Q:对于热更新包体的大小,最佳实践是多少?多大以上的更新建议不采用热更新而采用全包更新?如果一次更新的内容比较大,是否建议还是全包更新比较合适?包含多个AssetBundle。

A1:基本上现在AssetBundle都已经将其每个大小控制在5~10MB以下(5.3以前是1MB),这样就可以保证IO次数和热更新内容都尽可能小。

整包更新都不太好,会有大概10~15%的用户流失,所以能热更还是热更。热更新包的大小主要是去除冗余,因为LZ4本身已经是压缩级别了。

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

A2:国内渠道商比较多,获客成本比较高,所以换包的损失比较大,能走热更新还是尽量走热更新。

然后也可以考虑一下国内的一些第三方热更公司,比如乐变,他们支持无感知边玩边下,以热更新的方式替换主包。

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/613ac9728f8c8342419e8c17


Shader

Q:如下图所示:
1.现象:这些资源出现2份是什么原因?
2.目前Shader内存占用太高了,能否给些推荐建议?

1.png

A:1.在编辑器中,当GraphicsSettings里面设置了RenderPipelineAsset之后,RenderPipelineAsset最终会引用PostProcessData,PostProcessData中引用了各种后处理相关的Shader,所以打包的时候,会将各种后处理相关的Shader打包进包体,比如UberPost、Bloom等。

2.png

3.png

4.png

而且这些资源会在RenderPipeline初始化的时候被加载进内存。这是UberPost的第一个实例的来源。

2.当我们在游戏实时运行的时候,比如涉及到切换RenderPipeline的操作,使用了AssetBundle加载RenderPipelineAsset,这样在AssetBundle中就又有了一份PostProcessData,因此这些后处理相关的Shader就又被加载了一次。总共就有2份UberPost了。

3.对此我们建议所有的RenderPipelineAsset相关的资源都由AssetBundle处理,在Editor的GraphicsSettings中将RenderPipelineAsset移除。通过脚本来动态从AssetBundle中加载并赋值。

4.可以创建一个空场景放在所有场景之前,在这个场景中动态加载RenderPipelineAsset,并赋值给GraphicsSetting.renderPipelineAsset,如下图:

5.png

之后所有的问题都只要注意AssetBundle的冗余就可以了。

优化Shader:

1.UberPost的Shader可以考虑将用不到的Keyword给注释掉。如下图:

6.png

2.对于内存占用非常多的Shader,需要优化Keyword组合数量,建议参考《Stripping scriptable shader variants》(https://blog.unity.com/technology/stripping-scriptable-shader-variants),使用后处理来优化Shader变体组合数量。

7.png

感谢一直有点困的仓鼠@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/6135edec8f8c83424197b221


Performance

Q:关于手机发热问题,该从哪些方面入手?我们项目主要有大量PBR,另外模型都是高模。是不是手机性能越高,发热越明显?

A1:这个可以反推一下:
发热=耗电高
耗电高=GPU CPU高负荷
最有效的方式应该是先锁帧,然后就是想办法优化GPU和CPU了,针对这2个优化方案有很多,可以找找适合你们项目的。

感谢萧小俊@UWA问答社区提供了回答

A2:回答如下:
1.发烫的问题都是从CPU\GPU和IO入手的。
2.不是。性能越差,同样的计算力,发热才会更明显。这块个人认为是需要定位下耗时在哪里才好做判断的。没有统一说性能好发热也明显的说法。比如:你们做了分级策略,在高端设备上开的效果越大,那自然发热发烫就明显。

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

A3:发热是一定会有的,并不是说做好了之后就没有发热,而是多久能发热到多少度,达到一个预期就行:
1.首先要定好分级策略,其次再查对应分级设备上的发热问题。
2.还有就是先限制好30帧,做好30帧的发热问题,再去做高帧率的发热问题。
3.可以通过UWA的温度模块看发热的趋势,还是比较准确的,温度过高就会导致降频。
4.就我们项目解决发热的流程来看,发热与功耗是正相关的。

这个功耗可能是CPU,也可能是GPU,功耗可以通过PerfDog查看,也可以参考雨松的文章《Unity3D研究院之实时获取手机电流、电压、计算功率发热(一百一十八)》,分别测试CPU和GPU哪块功耗高具体定位一下。

PBR项目可能主要是GPU,GPU主要就是带宽和计算量,带宽占大头,带宽也分为两部分Read/Write Bandwidth。Read是上传几何信息和贴图,Write主要是写回到FrameBuffer和RT的存储,关于带宽可以使用Arm MS StreamLine工具或者PerfDog辅助查看一下(只有Mali的GPU可以看),到最后可能还是让美术去优化资源。

5.CPU的就要具体模块具体看了,注意线程的使用。Profiler看不到,当时我们就是遇到线程内的问题导致的发热,查起来比较麻烦。

感谢范世青@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/613acebc8f8c8342419e98ce


Script

Q:如何优化Delegate.Add/Remove这类堆内存分配问题?

A1:降低使用频率,尤其是不要在一个代理里加过多的函数,会导致其堆内存分配更大,因为其实现原理是复制一个List来使用的。

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

A2:其实Delegate的+= 是会有很严重的GC问题的,可以考虑用一个字典去代替。

8.png

感谢萧小俊@UWA问答社区提供了回答,欢迎大家转至社区交流:
https://answer.uwa4d.com/question/613ac2e28f8c8342419e7d5d

20210913
更多精彩问题等你回答~

1.Vulkan API的性能及兼容性
2.Unity TMP字体方案如何选择
3.如何实现AAB包的增量更新

封面图来源于网络


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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK