关于LZMA和LZ4压缩的疑惑解析

关于LZMA和LZ4压缩的疑惑解析

本期聚集话题:关于LZMA和LZ4压缩的疑惑解析;粒子系统是否能够支持GPU Instancing;有办法临时屏蔽掉脚本的一些编译Warning吗?...


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

UWA 问答社区:answer.uwa4d.com
UWA QQ群:793972859(仅限技术交流)


AssetBundle

Q1:昨天看到问答社区上UWA_Xin对LZMA和LZ4压缩的解答,在此有些疑问。

请输入图片描述
问题1:我在网上看到这篇文章提到,AssetBundle在加载的时候需要扩展出来一块内存来解压,我觉得解压这个说法是有问题的,因为如果都被解压出来了,就不需要LoadAsset了。资源都已经在内存中了,而我们测试的时候,用LZ4要比LZMA内存小了快200MB,所以我觉得LZMA是在加载AssetBundle的时候会把资源都解压出来的,并不是只是多了一个LZ4的AssetBundle大小。

我看了UWA关于《移动游戏加载性能和内存管理全解》的视频讲解,上面说用LZMA压缩的时候LoadFromCache在第一次读取时会很耗时,是由于Cache会把AssetBundle包重新压缩成LZ4使得第二次读取的时候速度加快,所以上面截图说的LZMA会把AssetBundle再压缩成LZ4其实只是针对的LoadFromCache这个接口而言的,而不是针对的LoadFromFile,猜想LoadFromFile是直接从硬盘读取的,不存在Cache的操作,所以上图是不是说得有误?

问题2:LZ4压缩AssetBundle包是按照Chunk来读取的,那么在解压AssetBundle包的时候一般是在读取AssetBundle的头文件信息,那么解压AssetBundle包的时候LZ4的Chunk优势是没有优势的吗?加载AssetBundle的时候LZMA和LZ4的速度应该一样的吗?(如果LZMA是完全解压整个包体就另当别论了)。

UWA:问题1解答:我觉得解压这个说法是有问题的,因为如果都被解压出来了,就不需要Loadasset了,资源都已经在内存中了。

解压和加载是两回事的。题主给的文章里说的解压是针对WWW接口的,WWW加载LZMA,是需要解压进内存的,但这个只能算是二进制流,相当于是未压缩的AssetBundle,后续的LoadAsset依然是要做的…但第二次调用的LoadFromCache就不用了,因为磁盘的Cache里已经是“未压缩的AssetBundle”了。

上面说的LZMA会把AssetBundle再压缩成LZ4,这不仅仅是针对LoadFromCache的,LoadFromFile也是一样,只是LoadFromFile是不Cache到磁盘的,完全在内存中进行,所以这个接口加载LZMA的AssetBundle一样会变很慢,同时造成内存的明显上涨。

问题2解答:根据问题1的解释,LZ4相比LZMA在加载AssetBundle的时候还是有很大优势的。但最后还是留下了一个疑问,而我们测试的时候用LZ4,要比LZMA内存小了快200MB,所以我觉得LZMA是在加载AB的时候会把资源都解压出来的,并不是只是多了一个LZ4的AssetBundle大小。经过这边的一些测试,这个内存的差异确实更加接近未压缩的AssetBundle的大小,而不是LZ4的大小。
所以题主可不可以再多做一步,就是把用到的AssetBundle打成未压缩的,看看是不是确实接近200MB呢?

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


粒子系统

Q2:粒子系统是否能够支持GPU Instancing?做了些例子都没能看到GPU Instancing生效。

UWA:Unity 2018已经支持Particle System的GPU Instancing了,不过必须是Mesh模式的,具体可以看这个文档

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


加载

Q3:如果我代码中声明了个Texture然后加载了图片,是不是无论我的这个Component销毁或者这个GameObejct销毁,都不会释放这个Texture的内存?必须在OnDestroy 里销毁才可以呢?

因为某张Texture的内存只会有一份,但是可能会被多个对象引用,所以不可能跟随Component或GameObject的销毁而销毁。
估计是考虑到资源管理(某张Texture当前帧不用了,可能过两帧又要用了,而这部分IO消耗不小,所以需要开发者自行管理),所以这部分并没有走GC。使用Resources.UnloadAsset卸载Texture。
感谢凯奥斯@UWA问答社区提供了回答

Component销毁 或者 Gameobject销毁都不会卸掉new出来的Texture的内存,需要调用Object.Destroy()方法,把new出来的Texture对象作为参数传进去,然后查看Profiler就可以验证。
感谢上午八点@UWA问答社区提供了回答

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5aeb75010e95a527a7a81ca4


编辑器

Q4:有办法临时屏蔽掉脚本的一些编译Warning吗?比如:The variable 'xxx' is declared but never used之类的。

File->Build Settings->Player Settings->Logging
感谢凯奥斯@UWA问答社区提供了回答

强烈建议题主修掉这些Warning,而不是屏蔽掉它们。我觉得,程序保证代码没有Bug是底线,没有Warning是合格线……尤其是你举例的这种,虽然编译器会帮你做优化,但是保不齐什么时候写其他逻辑的时候会坑了你。
感谢贾伟昊@UWA问答社区提供了回答

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5afe9e8e0e95a527a7a81e2c


动画

Q5:游戏在运行一段时间后,出现了一个CPU高占用函数:Director.ProcessPlaySateChanges ,它产生了3616ms的耗时,请问这是怎么产生的,确认C#代码中无此方法调用,有人遇到过这个问题吗?(版本Unity 5.6.5p3)
请输入图片描述

经排查已找到原因,是UI中的一个播放动画前调用了函数 Animator.Rebind()导致的。

感谢张剑@UWA问答社区提供了问题和回答,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5afebe1b6b104d27ac3aadb6

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

官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(仅限技术交流)