• Unity NGUI C#性能优化


    建议读者先看这篇博文:http://blog.csdn.net/zzxiang1985/article/details/43339273,有些技术已经变了,比如第1招,unity5的打包机制已经变许多了。不像其他招基本还是可以学习的,比如:透明通道分离,关闭texture read/write选项(其实其他资源得read/write选项也类似,比如动画资源等),减少场景中的GameObject数量,整理图集(一般是一个面板使用2个图集:当前面板一个图集+基本图集),使用多个UIPanel隔开dc避免一个dc改变却重绘大量dc等。

      一、下面是我主要针对减少ngui的dc做法进行补充:

        第一,我们需要知道ngui的dc是UIPanel隔开的,每个uipanel管理自己的dc;

        第二,对于一个uipanel,每个dc有自己的uiwidgets列表,有自己的纹理/材质,和uipanel分配的深度depth范围,dc合批的情况:纹理一样,材质一样,并且2者的深度范围是相邻的,就会合批。合批之后,新dc的深度范围包含2个dc范围(其实看过源码的都知道这种说法是不对的,正确的是,每加入一个uiwidget,uipanel会根据它的纹理材质深度给它找一个现有dc:纹理一样,材质一样,并且2者的深度范围是相邻的,找不到就新建一个dc给它);

        第三,dc的重构:包括2种:uipanel.FillDrawCall和uipanel.FillAllDrawCalls,顾名思义,前者是给某个dc重绘,后者是给该uipanel所有dc重绘,这在文首那篇博文提到了。

          第一种重构是当某个dc.isDirty时重绘:这里只谈非手动重绘且是运行过程中重绘的情况:

           1.dc的uiwidgets中有顶点变化,顶点位置变化或者有widget透明度变化(一个widget的透明度由整个widget的垂直结构决定,自己的*父亲的*父亲的父亲的...)

           2.removewidget时,所以尽量不要运行时removewidget

           3.addwidget时

          第二种重构是当uipanel.mRebuild=true时重绘:这里只谈非手动重绘且是运行过程中重绘的情况:

           1.addwidget时,如果找不到现有的dc给它使用,mRebuild=true,

           2.removewidget时,如果该widget的有dc且该dc的深度是uipanel中所有dc深度的最小或最大深度时,mRebuild=true

       总结:

        对于第一,uipanel很少时,dc之间会影响很大,要是某个dc经常导致FillAllDrawCalls,那就大家一起遭殃,但如果uipanel很多,本身就增加了很多dc,因为uipanel之间的dc是独立的,不能合批的,所以项目中也不要滥用uipanel;

        对于第二第三,实际应用时,一般把跳字,血条等经常重绘的的ui分出去作为一个uipanel,主面板的uipanel可以这样分割成:staticpanel,movepanel1,movepanel2...,并且可以看到remove和add widget对重绘影响很大,所以尽量不要运行时干这两件事,除非你知道会发生什么。

        此外,对于一个系统的面板,一般使用自己的图集和公共图集,这个时候要特别注意尽量合批dc,避免各个不同图集uiwidget的depth交叉导致相同图集widget的dc不能合批,我在制作UI面板时一般<1的深度给背景图,1-9给公共图集,10-20给该系统的图集,50-60给公共图集,这样就基本做到:能合批的都能合批,实际工作上要养成点击uipanel的showdrawcall,打开dc显示面板,查看是否分割的太厉害或者能否合批,的习惯。

     二、对UIScrollView的优化:如果大量GameObject挂到Scrollview下面的话,会导致卡顿,可以通过设置不显示的gameobj为false来减少卡顿。

     三、用List<int>和Dictionary<int,xx>代替List<enum>和Dictionary<enum>,因为后者在各种操作中经常调用其equal函数: 

        比如List<T>的equal会调用T的default EqualityComparer,而The default EqualityComparer for enums uses the Enum.Equals method:
        public override bool Equals(object obj)=》有装箱拆箱操作,增加了gc(Dictionary类似)

     四、用for代替foreach遍历list,用var iter=dic.getenumtor(); while(iter.movenext()){}iter.dispose();遍历dic,这个是unity自带mono的bug,会多装箱拆箱操作导致gc。读者先检测自己的Unity版本是否修复了此bug,如果修复了则忽略此条。

     五、lamda表达式会导致gc,原因是每次调用lamda表达式时new出了一个托管对象,所以如果lamda内部函数不需要使用外部函数的数据变量,那就不要使用lamda。

  • 相关阅读:
    PHP数据采集curl常用的5个例子
    【荐】PHP采集工具curl快速入门教程
    PHP常用正则表达式
    JavaScript方法call、apply、caller、callee、bind的使用详解及区别
    axf、elf文件转换成bin、hex脚本工具
    为什么数据须要做爱
    POJ 3978 Primes(求范围素数个数)
    Facebook Hacker Cup 2015 Round 1--Homework(筛选法求素数)
    后台进程整理
    Nginx优化具体,应对高并发
  • 原文地址:https://www.cnblogs.com/Tearix/p/6941426.html
Copyright © 2020-2023  润新知