技术分享连载(四十)

技术分享连载(四十)

精选5个性能优化问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:793972859


资源管理

Q1:我们有了解到,卸载AssetBundle后, 从这个AB读出资源的Instance ID和guid的映射关系会被删除。在我们的项目中, 优化策略是这样的: 进场景时, 预加载Prefab,并创建一些对象实例缓存,然后会把AB删掉。因为我们发现在Android机器上, AB占的内存很大, 如果其中纹理(A)的Instance ID被认为失效,它和guid的映射没有了,如果某个时刻,缓存池不够用,需要从Prefab创建一个新的实例,这个Prefab会引用到A,资源管理器发现这个A的guid并没有对应的实例ID, 这时会导致重新从磁盘上加载资源A,请问这样理解对吗?

Instance ID和"guid"(类似Editor中的guid,但本质上不是)的映射是在发生加载操作时才需要的,如果一个Prefab需要的资源都已经加载好了(通常第一次实例化就都加载好了),那么后续的多次实例化都是不需要那层映射关系了的。所以理论上这种情况下卸载AB是没问题的。另外,Unity是不会自动"从磁盘上重新加载A"的,对于AB中加载出来的资源,"磁盘"就是指内存中的ab文件,如果AB已经卸载了,那么重新加载的结果就是资源丢失。发生冗余的前提是,这个AB又被手动加载进内存。


资源管理

Q2:UWA的测评报告上说“蒙皮网格(Skinned Mesh)数量过高”,我们游戏内很多模型动画用的是这个,是美术还可以用其他的方式做动画吗?

http://blog.uwa4d.com/archives/Simple_PA_Animation.html

随着研发项目越来越重点,蒙皮网格数量必然会越来越多。报告中“蒙皮网格过量”仅是一个提醒,它在性能方面最主要的影响其实是MeshSkinning.Update和Animation.Update/Animator.Update,建议这个研发团队在看到“蒙皮网格数量过多”提醒时,重点看一下动画系统性能页面中的CPU耗时是否较高。如果较高,则建议根据我们动画模块优化Blog中的建议去完善项目动画模块即可。


资源管理

Q3:能否推荐一些动画剧情的插件?

我们推荐Asset Store中的uSequencer插件。具体的相关文章可参见:
1)Usequencer 初识
2)Usequencer 准确显示瞬时事件&持续事件


动画

Q4:我在Profiler中看到Animator.Initialize这个耗时很大,这个有什么建议么?Animator.Instance 是因为Animator过多造成的吗?

由图中可知,Animator.Initialize主要是在Instantiate实例化时引起(实际上,GameObject.Active操作也会引起Animator.Initialize),而其具体的耗时原因是相关资源(主要是AnimationClip资源)的加载所致。因此,我们的建议如下:
(1)对GameObject的Instantiate实例化操作进行检测,对于频繁Instantiate的GameObject尝试进行缓存;
(2)对Animator Controller中的AnimationClip资源进行精简,可尝试动态加载和替换Animator Controller中的AnimationClip;
(3)由(1)引申出来,对于已经在缓存池中通过GameObject.Active操作造成的Animator.Initialize开销,建议通过Active/Deactive Animator组件来代替Active/Deactive GameObject,这种操作可以避免Animator.Initialize时内部组织结构创建的开销,进而降低Animator.Initialize时的CPU开销。
0.png


资源管理

Q5:请教一下,为什么NGUI的Atlas通过AssetBudle载入之后,使用Resources.UnloadUnusedAssets()不能够释放呢?分析器里面引用是1,但是又找不到哪里引用了。

如果Unity Profiler中看到了资源的引用计数不为0,则说明该Atlas资源还在被索引,这样使用Resources.UnloadUnusedAssets()是无法进行卸载的。只有将其索引消除,该资源才会被认为是UnUsed资源,这样才能被Resources.UnloadUnusedAssets()卸载。该资源的引用计数不为0的原因可能有以下几种:

(1)它被缓存在某些Container中,即它从AssetBundle或Resources中加载后,被直接缓存到某个容器中,从而产生了索引,只要它没有被清除出容器,那么索引将一直存在;

(2)它被其他Material、Prefab等索引,而这些资源被缓存在某些容器中,即间接被容器缓存,只要索引它的资源不被清楚,那么它的索引页将一直存在。

就目前我们遇到的泄露问题来看,上述两点为最为主要的原因。因此,如果你的项目中也存在类似情况,建议首先以此为基础对容器的使用进行排查。

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