技术分享连载(九十六)

技术分享连载(九十六)

我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。

UWA QQ群:465082844
UWA 问答社区:answer.uwa4d.com


资源管理

Q1:最近在做包体压缩,发现有些动画文件的AssetBundle文件比较大,观察发现是其中包含的Clips较多,但是这些Clips都是复用的,而只是动画轨上挂的事件不同,所以创建出来的。

我们使用了LZ4的压缩格式,这个文件的大小大约是800K+,偶然测试使用了非LZ4的形式来打包,这个文件的大小大约是60K左右,相差有10倍以上的差异,这个就比较奇怪。
不知道有没有别的项目遇到过这样的问题,我尝试从原理上理解:

对于这种重复的动画,数据是可以复用的,动画事件相当于存储一些额外的配置就够了,所以理论上增加这种复用式的Clips不会对AssetBundle文件有多大的影响。LZ4因为要支持Chunk式的加载,所以复制了动画信息到所有的Clips的Chunk上?因此数据比较大?
想问下我的猜想是否正确,这种情况下,有没有什么好的方法压缩一下这块的体积?

两种格式下的AssetBundle文件大小差异:
请输入图片描述

是可能存在这个问题的。使用了LZ4压缩的动画文件AssetBundle大小,与Animation面板中Clip的数目和每个Clip的大小成正相关。

因为无法看到源码,只能说下我的理解:在打包AssetBundle时如果选择LZ4压缩,其将动画文件中的每个Clip作为独立的资源来单独压缩,这样可以保证在解压时只解压需要的Clip,但这样也就隔断了不同Clip间重复数据的复用,从而造成AssetBundle体积随Clip数目增加而变大。一个简单的例子就是,当你增加多个哪怕是完全相同的Clip时,AssetBundle文件也会随着Clip数目增多不断增加(很容易超出动画Fbx的大小)。

而默认的LZMA压缩,压缩时将整个AssetBundle作为一个整体(当然解压时也需要对整个AssetBundle解压),因而能充分复用不同Clip间的重复数据,因此,压缩后的AssetBundle大小对分割的Clip并不敏感。同样的例子,对动画文件增加多个Clip后,使用LZMA压缩的AssetBundle依旧会保持很小,而且增加不同的Clip数目,其大小也基本不变。

如此一来,如果要通过压缩减少动画文件AssetBundle体积,可以对解压速度不太敏感的动画文件用LZMA压缩。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a5cbf773513a24bd4ee76e2


资源管理

Q2:我在Unity 5.3.8 和5.6.5 下进行同样的设置,为什么FBX打出来大小相差那么大?
Unity 5.3.8 :35K,
Unity 5.6.5 :400K,相关的例子已经上传至UWA问答网站。

看了下题主的AssetBundle文件,可以提供以下线索:

Unity 5.6的Bundle:
请输入图片描述

Unity 5.3的Bundle:
请输入图片描述
可以看到两个Bundle的差异在Shader,然后在Unity 5.5的更新文档中看到:
Shaders: Shaders are now exported to the Unity player completely in binary. There is no Shader text string and parsing in run time.
也就是说,Unity 5.6的Bundle中Shader已经被编译为二进制,而Unity 5.3的Bundle中仍然是Text的Shader,从而导致了Bundle的不同。

该问题来自UWA问答社区,感谢 Saber 提供了回答,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a5ecc8ce6353e6be1f4342e


资源管理

Q3:我场景打包的AssetsBundle每次都不一样,和这个问题类似(https://answer.uwa4d.com/question/58d24e477dc35e7f0efb470f )。 我已经修改了Strippt Shader的设置,并且每次都在同一个空场景下打包,但是打包出来的CRC值不一样。

我每次都是先删除本地资源,然后从SVN上CheckOut下来再打包。场景用到的Shader单独打一个Bundle,这个Shader的包也是不同的。并且Unity 5.6.2的打包API只是一个根据Bundle Nname打包的函数,我无法实现每打一个就切换当前场景。

首先相同资源多次打包确实是会出现MD5不同的,这个问题之前在Unity的Roadmap中是提到的,现在找不到了,说明可能在某个新版本中解决了。

但在之前的版本中,已知的有两种可能会导致场景的AssetBundle的MD5变化,一种是题主提到的那个问题(Shader Stripping),另一种是开启Static Batching后,每次打包生成的Combined Mesh(或者其次序)可能不同。当然可能还有别的原因。

所以,建议通过AssetBundle的Hash值来判断内容是否发生变化(Shader Stripping的问题是会导致Hash变化的,而Combined Mesh那个问题是不会改变Hash值的),也可以通过AppendHashToAssetBundleName选项,直接把Hash值作为AssetBundle名字的后缀来查看。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a58b1b2332fcc45bafb1d95


其他

Q4:请问,WWW或UnityWebRequest通过域名下载AssetBundle,如何得知资源的实际IP地址?我用Dns.GetHostAddresses有时候会得到两个IPv4的地址,我如何知道实际连接的是哪个?

我用Dns.GetHostAddresses的IP会变化,所以感觉不能保证WWW实际连接的IP是我上一次用Dns.GetHostAddresses取到的IP。需求是要log客户端在不同地区连接的CDN节点IP和资源下载速度。

域名和IP本身就不是1对1的关系,一个域名可以解析出多个A记录或者CNAME记录(例如CDN)。

Dns.GetHostAddresses获得就是域名对应的A记录信息,可以参考dig命令的输出。一般来说可以自己对返回的IP进行遍历来分别尝试使用。

至于WWW或UnityWebRequest内部是如何实现这个不确定,也许就是只处理得到的第一个IP,也许会对每个IP都进行尝试直到成功。

该问题来自UWA问答社区,感谢Jay提供了回答如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a5d71adf6dfce42a1f8ebd2

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

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