您的位置:首页 > 其它

Q&A——资源管理(八)

2017-03-31 17:08 218 查看


资源管理

Q1: 我使用Shader.WarmupAllShaders操作,在后续加载资源还是有CreateGPUProgram出现。(Shader都在一个AssetBundle文件中,都是常驻内存的,不会删掉)是必须使用ShaderVariantCollection来加载Shader吗?

A:以上这种问题的较大可能是:Shader被打包到不同AssetBundle中了,WarmupAllShaders仅能对当前内存中的Shader进行warm up。后续如果又有Shader加载进来,则仍然会出现CreateGPUProgram操作。

建议开发团队使用UWA的资源检测工具,检测下AssetBundle中Shader的具体打包情况,查看是否出现了冗余打包的问题。


资源管理

Q2: iOS上方形POT图片有时候会失真,请问这种情况如何避免?一张NPOT的图变换成POT,是否有推荐的方法? 采用 ToLarger 的模式拉成POT是否会有损失呢?

A:如果可以的话,建议直接将其制作成POT图片,而非进行二次转换。ToLarger确实可以将纹理拉伸成POT纹理,但如果是UI界面(开启Pixel Perfect)的话,可能显示时会有较大视觉损失。


资源管理

Q3:AssetBundle在使用时解压出来的资源会占用一定的内存。我们现在想尝试使用两种加载方式:(1)在AssetBundle加载相关的资源后,将资源进行缓存,并卸载AssetBundle文件;(2)对AssetBundle文件进行缓存,以后用到相关资源后再进行直接进行加载。请问这两种方式你们推荐哪一种比较好?

A:对于Unity 5.3版本之前的项目,建议通过LoadFromCacheOrDownload或LoadFromFile的方式来加载AssetBundle,这样既可以降低Assetbundle对象的内存占用,又可以保持AssetBundle与资源之间的链接关系,从而方便后续具有依赖关系的Prefab的加载。

对于Unity 5.3版本之后的项目,可以从AssetBundle打包本身进行处理。即:使用LZ4格式的AssetBundle文件,而不使用默认的LZMA格式。同样可以达到上述的需求,稍有不足的是,LZ4格式的AssetBundle文件较之LZMA格式的文件占用稍大。

如果是依赖关系打包,对于被依赖的共享资源AssetBundle文件,我们还是建议将其缓存在内存中,虽有一定的内存增加,但可以通过上述办法极大地降低内存上的占用,缓解内存压力。


资源管理

Q4:在Unity 5.x版本下,我们在用UGUI的过程中发现它把图集都打进了包里,这样就不能自动更新了,请问图集怎么做自动更新呢?

在Unity 5.x中UGUI使用的Atlas确实是不可见的,因此无法直接将其独立打包。但我们建议,可以把Packing Tag相同的源纹理文件,打到同一个AssetBundle中(设置一样的AssetBundle Name),从而避免Atlas的冗余。同时这样打包可以让依赖它的Canvas的打包更加自由,即不需要把依赖它的Canvas都打在一个AssetBundle中,在更新时直接更新Atlas所在的AssetBundle即可。


资源管理

Q5:图中的Material.SetPassFast占用很高,这是我在第一次实例化一个特效,但是第二次实例化就不会出现高值了,请问能怎么优化吗?



该过程是在处理Shader,Unity 5.3以后在第一次显示时才会将Shader进行Warmup,所以就会造成一次峰值卡顿。研发团队可以参考我们之前的分享:Unity加载模块深度解析之Shader篇以加深理解。


资源管理

Q6: UWA建议“尽可能将静态UI元素和频繁变化的动态UI元素分开,存放于不同的Panel下。同时,对于不同频率的动态元素也建议存放于不同的Panel中。”那么请问,如果把特效放在Panel里面,需要把特效拆到动态的里面吗?

通常特效是指粒子系统,而粒子系统的渲染和UI是独立的,仅能通过Render Order来改变两者的渲染顺序,而粒子系统的变化并不会引起UI部分的重建,因此特效的放置并没有特殊的要求。


资源管理

Q7:我在UWA上进行了性能检测,在资源内存这里看到详情如下。请问这个数量峰值大于1是不是就是有问题的?但一个Material是很可能被实例化多份的。实例化后对象释放掉,然后清理掉原始的Material,按道理就不算冗余吧?毕竟大部分都是材质在操作,对贴图资源应该没有影响。而且,如果确实有那么多角色同屏怎么办呢?



是的,如果数量峰值>1,则说明存在资源冗余的风险。如果是Material实例化,那么后者是有个(instance)后缀的,比较好识别。如果是new Material(Shader)出来的,那么是没有instance后缀的。但无论是哪种方式,如果数量峰值较大,都应引起大家注意。一般都是可以通过其他方法来尽可能避免冗余的。

如果变化不是随机的,且Material参数变化情况比较少,那么可以根据参数的变化情况只做几种Material,然后通过脚本动态赋值。如果是随机或者动画,那就没什么办法了,要么改需求,要么就接受这么多。


资源管理

Q8: 对NGUI字体错乱有什么好的解决方案吗?

有这么几种可能:

一次展开文字太多了。这种情况在部分高通机型和Unity早期版本上都经常出现,现在也偶尔有,究其原理是FontTexture的扩容操作做得不够快或者收到了硬件驱动的限制。

一般来说有两种方法可以解决:(1)减少面板中的字体内容;(2)一开始就用超大量的字体去扩容,将动态字体的FontTexture扩大到足够大;

文字渲染与开发团队编写的多线程渲染发生了冲突。这种情况也常有发生,特别是通过GL.IssuePluginEvent方式来开启多线程渲染的项目,就会容易出现问题。

就我们的优化经验来看,第一种情况发生的可能性比较大。


资源管理

Q9:我们测试发现,当Animator Controller挂载的动作比较多时,即使切换成另外一个动作很少的Animator Controller,任务的动作信息还是不会释放。我们将英雄打成一个AssetBundle,然后又把定制的Runtime Animator Controller加载替换进去,英雄自带的Runtime
Animator Controller是挂了所有动作的。我们试了替换Runtime Animator Controller之后,把先前的Runtime Animator Controller Destroy掉,貌似内存也没释放。





销毁Animator Controller并不会释放其内所引用的AnimationClip资源的,所以内存没有明显下降是正常的。建议按照以下方式做个试验:

销毁Animator Controller 后,通过Unity Profiler立刻真机Take Sample,查看Animation Clip的Ref count是否为0;

如果不是,则需要进一步查看这些资源的索引出处;如果为0,则可以通过UnloadUnusedAssets或UnloadAsset来将其从内存中去除。


资源管理

Q10:请问这个GameObject.Active的开销怎么这么高?Activate会产生堆内存分配吗?



这个是PC上的鼠标交互事件造成的,是UI界面的Active操作,所以触发了各种相关的OnEnable调用,研发团队可以在Profiler中进行进一步定位,查看根源。

一般来说,GameObject的Activate操作本身是不会产生堆内存分配,但它引发的各种底层类的OnEnable会产生堆内存的分配。开发团队可以参考这里加深理解:
http://blog.uwa4d.com/archives/Simple_PA_NGUI.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: