NGUI开发优化技巧

屏幕自适应

& Scaling Style(UIRoot上)

    主要用Constrained设置(content width和content height)进行整体布局

&UIRect

    主要是UIWidget上进行调节(因为UIWidget继承自UIRect),上边有Anchors,去对应特定锚点即可。

    Anchors上的Execute(OnEnable 、OnUpdate、OnStart)尽量用1,3  因为2会每帧计算,所以如果项目中UIRect.Update()高的话,就需要检查下这里设置是否合理。

事件处理

尽量设计一个EventListenerMgr的管理类,统一管理按钮的点击,把它挂在UIRoot上,然后去获取到它下边的所有Button,然后通过UIEventListener.Get(button.gameObject).onClick += OnButtonClick去注册上函数即可

NGUI优化

可以通过NGUI自带的DrawCall观察工具去定位DC高的地方:如下图

可以先在PanelTool中找到高DC的Panel,然后再去DrawCallTool中选中SelectPanel,去分析所有DC,如果发现材质相同且顺序相邻但是没有合并的,那么就是需要优化的(一般是用了Texture,导致的)如下图绿色线:


解决方案:只需找到这些共用的纹理,打成图集即可。(利用NGUI的AtlasMaker)

而对于出现的材质相同,但是顺序间隔的(一般是层级深度设置不合理导致的),如下图:


解决:这种则需要去调节他们的depth深度值,来解决(在不改变效果的前提下)

NGUI更新开销

一般会涉及这几个函数:UICamera.Update()  UIRect.Update()  UIPanel.LateUpdate()  UIRect.Start() 其中UIPanel.Update()是最主要的一个。

如何判定UI部分开销是否合理:

如果看到UIPanel.LateUpdate( )开销控制在3、4ms以内的话,基本是比较合理的。

它对堆内存的开销,一般也是由于UIPanel.LateUpdate()造成的。

它对渲染的影响,体现在Mesh.CreatVBO( ),因为场景中的一些透明的材质、模型一般是不会变化的,因为一般是静态的,而UI部分一旦出现这个函数的开销较高,一般很可能是因为UI部分网格的刷新过于频繁导致。

高内存分配列表中,如果UIPanel.LateUpdate( )开销在10~20兆之间的话,认为是合理的。如果这部分堆内存分配很高的话,一般也可以认为UI的开销不太合理。

进行优化:

首先UILabel的更新开销

如果发现Font.CacheFontForText( )开销较大,则一般为动态字体的问题(尤其是字数较多时,每次变化,更新都会动态更新到字体的纹理里边从而使得该纹理会越来越大)如下图:

通过Label找到所用的字体,再通过字体找到字体的材质,最后通过材质找到纹理(看到每次出现新的动态字体,这张纹理都会变大256x256 变成256x512等),字体大小不同的话,在纹理中的区域也会不一样,也就进一步撑大了纹理




解决方法:对于一些频繁出现的固定字,可以做成静态字体,因为静态字体的这张纹理是确定好的,就不会调用这个函数了。

UILabel的Effect,对于一些需要频繁移动的一些字体,尽量少使用OutLine和OutLine8(会增加顶点数,网格数分别4、8倍)


当然,以上字体的优化,只针对于动态字体和会变颜色的,因为静态字体的话没有影响,因为不会去刷新网格。


                                                         UIPanel更新机制

 会先根据UI元素的depth进行排序渲染,然后会根据相邻元素(注意要depth相邻)是否来自于同一图集来确定是否进行合并DC!

                    分为两种:①更新单个UIDrawCall   和  ②更新所有UIDrawCall

            ①对于频繁变动的UI元素,其所在的UIDrawCall面片数越少越好(eg:下图中只有这一个血条是变动的,而除去NGUI哪个,其他都是和血条一个DC里的(都是DC1),那么只有血条动也会引起整个大Mesh的重建)



②更新多有UIDrawCall情况,比如下图中,本来是两个DC,第二个DC depth在294~304之间,而把第一个DC中一个文本depth改为295,这打断了第二个DC,从而导致所有UIDrawCall的重建(这个重建并不是智能的将第二个DC进行拆分为3个,而是全部销毁GameObject.Deactive再重新生成GameObject.Active)     当然这也会影响渲染部分的Mesh.CreatVBO( )网格的重建,甚至比网格渲染Mesh.DrawVBO( )开销还大。


对于这种,解决方法:  

          动静分离 :最快的方法是给单个动的部分添加UIPanel组件,虽然DrawCall变多,但UIPanel的消耗远比不分离时的整个网格重建消耗小的多

            调整depth:不让它去影响其他DrawCall(eg:第一个图中的文本的depth打乱了NGUI例子那个DrawCall)

            独立为UIPanel:如把上边的文本显示与否,动态的这部分独立出来,这样就不会有大网格的重建了(即:没有了GameObject.Active 和 Deactive),渲染那边的Mesh.CreatVBO也会小很多,因为独立出来了面片边少了



猜你喜欢

转载自blog.csdn.net/ai_little_ai/article/details/80535310