技术分享连载(四十七)
- 作者:admin
- /
- 时间:2016年12月27日
- /
- 浏览:4751 次
- /
- 分类:厚积薄发
本期话题:WebStream 内存释放、销毁Instantiate实例化资源、UI Image组件的Sprite剪裁显示...精选5个性能优化问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。
UWA QQ群:793972859
资源管理
Q1:对Prefab资源的卸载、预览英雄模块、需要卸载英雄角色的资源、动画和材质都可以通过Resources.UnloadAsset(xxx)来顶点清除,而Prefab不行,Prefab 只能用 Destroy + Resouces.UnloadUnused()卸载吗?
Prefab如果想要单独卸载,只能使用DestroyImmediate来实现。同时,考虑到Prefab本身已经是很小的一个壳了,对内存的影响非常小,一般情况下是在切换场景的时候一起释放的。
资源管理
Q2:如果我用WWW加载了一个AssetBundle,创建了一块WebStream内存。这时候我用另一个东西保存这个AssetBundle的引用,然后用WWW给Dispose了,那么这块WebStream内存会释放掉么?
如果仅是www.dispose,但是AssetBundle引用依然保留的话,那么WebStream是不会释放的。WebStream存在两个引用,一个是www对象,一个是加载出来的AssetBundle。仅这两个引用全部消除时,WebStream才会被Unity引擎回收,具体说明可见之前的技术文章:Unity AssetBundle内存管理机制详解。
资源管理
Q3:NGUI的UIEventListener中的OnPress与UIButton的Press状态不能对应上。具体情况是我点击某个按钮并且按住不放,UIButton处于Press状态,然后移出了Button的范围,UIButton的状态变回了Normal,而UIEventListener中的OnPress并没有监听到,必须松开点击才能监听到。它们的Press状态切换有什么不一样呢?
理论上UIButton的OnPress和UIEventListener的OnPress是在相同时间点触发的,即手指按下和手指抬起这两个时间点上。而手指在按住状态下移开按钮时, UIButton的状态会变为Normal,这是因为其响应了OnHover的消息。因此如果要模拟UIButton的行为,至少要配合使用OnPress和OnHover两个消息。
资源管理
Q4:关于UI的Image组件的Sprite剪裁显示问题。因为Image组件上面有ImageType为Filled的选项,通过这个东西可以实现对UI的各种奇妙的显示。因为Mask组件会造成大量的Batches,单独做图会造成算是冗余内存和包体开销,那写个自定义继承Image的组件把这个效果给实现了,按道理是没有问题的,而且在翻看UGUI源代码的时候,也找到了相关片段:
目前对我来说有两个疑问:
1. 假如,我只是单单的想把方形的内容显示成圆形的内容,光靠目前的属性、参数等,能否用一套算法把它算成圆形的呢?
2. 假如说上面的第一个假设是OK的,也假设剪裁成圆形的算法效率也是还行的,那么最终的性能开销是否值得?
对于提问中所提的需求而言,这是一种有意义的做法。即,通过多边形拼成特定形状来避免Mask组件的使用和UI资源的冗余。而对于圆形,由于需要通过多边形来近似地拼出,通常就需要生成较多的顶点数。因此特别需要注意的是:尽可能确保该UI元素是处于“静态”(不会频繁地出现变化的UI元素)的UIPanel中,因为顶点数较多的UI元素会对UIPanel的网格更新带来明显的开销(比如文字的outline效果)。
资源管理
Q5:我发现如果不调用UnloadUnUsedAssets这个函数,则无法销毁通过Instantiate实例化出来的材质(包括纹理)。如果我尝试用Resouces.UnloadAsset来卸载挂在GameObject上的实例化材质, 则会闪退,请问这种情况该如何解决呢?
如果想要直接销毁通过Instantiate实例化出来的材质、纹理等资源,则只能使用DestroyImmediate来进行销毁。研发团队可以参考NGUI中UI Draw Call组件里对动态材质的处理,来加深对动态创建以及销毁的理解。
今天的分享就到这里。也欢迎热爱进步的你加入UWA的QQ群(793972859),也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。 比起闭门造车,我们更乐意与大家各抒己见,畅所欲言;比起形而上的泛泛而谈,我们更乐意与大家直击痛点,对症下药。