技术分享连载(四十五)

技术分享连载(四十五)

本期话题:GC 优化、Resource.Load 加载 、Font Texture 动态字体...精选5个性能优化问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。

UWA QQ群:793972859


资源管理

Q1:我从UWA的报告中看出我们的GC比较严重,里面有我们自己GC的地方(切换场景的时候),然后就是系统GC的。这个我们无法控制,那么有什么办法优化吗?我发现一个很尴尬的地方,如果我们不自己去GC,内存好像不会返回,但是GC又会引起卡顿。

一般来说,手动调用GC都不太必要,而切换场景时多数情况下会因为堆内存的大量分配导致系统GC的自动触发,但这里的卡顿相对可以接受(只是稍微增加了切场景的时间)。但在非场景切换的时间里,如果系统GC也频繁出现,那么就需要对脚本的堆内存分配进行严格的控制,可以通过查看堆内存分配的TOP10函数,逐个进行分析和优化,减少各个函数的累积堆内存分配量。另外,内存的下降与GC并没有十分的关联。开发者需要注意两点:首先,在Android平台上,GC无法降低Mono部分的总内存(只是把空闲内存变大);其次,Unity部分的内存是通过Resources相关的接口来释放的,GC的操作对这部分内存也没有直接影响(理论上只要引用某资源的GameObject被销毁,那么该资源就能被Resources.UnloadUnusedAssets卸载,因此和GC也没有直接关系)。


资源管理

Q2:场景切换完了后,我们发现上个场景的内容并没有卸载完毕,所以我们调用了Assetbundle.Unload(true)这个函数,紧接着我们调用了UnloadUnusedAssets+GC操作帮我们清理资源(如果不调用后续两个操作的话,我发现内存曲线并没有得到明显下降),而这个时候GC次数又高了,GC次数高了CPU降低,不去GC内存得不到完整释放。我在你们网站上看到说不要开发者频繁去使用UnloadUnusedAssets+GC这个操作,所以希望得到一些帮助。

通过LoadLevel等API来切换场景时,Unity会自动触发Resources.UnloadUnusedAssets的操作,但在切换完成后再次调用Resources.UnloadUnusedAssets来确保卸载完全的做法也是较为常见的,而我们网站上主要是建议开发者不要在其他的时间点来手动调用Resources.UnloadUnusedAssets,在切换场景时还是可以酌情调用一次的,另外对于大场景的MMO类型的游戏,因为切换场景的频率较低,也可以考虑每隔几分钟来手动触发一次Resources.UnloadUnusedAssets来降低内存。而GC的话,则不建议手动调用,即使是在切换场景时。


资源管理

Q3:我们没有使用AssestBundle的方式,使用的都是在Resources路径下的Load,请问Resources目录下的所有内容都会加载到内存里吗?如果里面东西多,是不是会导致占用内存过高?

不会,Resources.Load也是即用即加载,但就目前我们统计的结果来看,Resources文件下的资源越多,其生成的ResourceManager内存占用也越大,研发团队可在Unity Profiler中通过Take Sample来进行查看。


资源管理

Q4:请问下,Unity 5.3.3版本,Android用AssetBundle.LoadFromFile读取Application.streamingAssetsPath目录下的AssetBundle文件,用什么样的地址?

在Unity 5.3之前,安卓上加载 StreamingAssets 目录下的 AssetBundle 时,可以直接使用 Application.streamingAssetsPath 作为目录路径,而Unity 5.3之后,通过新增的LoadFromFile接口加载AssetBundle时,则需要改为 Application.dataPath+"!assets"。具体也可参考雨松的博客http://www.xuanyusong.com/archives/4033


资源管理

Q5:Font Texture 资源是如何生成的,因为我发现好像有重复的出现,如何优化呢?

这是Unity为动态字体自动产生的纹理,一般来说不用特别关注。即使重复出现,里面的内容一般也是不一样的(内容即屏幕上显示的文字)。

今天的分享就到这里。也欢迎热爱进步的你加入UWA的QQ群(793972859),也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。 比起闭门造车,我们更乐意与大家各抒己见,畅所欲言;比起形而上的泛泛而谈,我们更乐意与大家直击痛点,对症下药。