关于UGUI的个人优化总结

尽量少用outline,tiled Sprite

如果用,尽量保证不会改变他的颜色大小之类的

减少其所在canvas重建

 

ugui为队列制,在队列才刷新,无改变不刷新

Ugui大量静态不改变的开销很低,对象池中对象用scale= 0或者alphaGroup = 0来控制更佳(伤害界面优化,改成alphaGroup,存到对象池中) Ugui scale = 0,顶点数也会变为0,ngui只是网格变为0,顶点数不变,所以要用color.a=0

 

写插件(动态设置图片层级,通过list保存indexsetsibling

慎用,容易增加drawCall

 

 

Canvas.BuildBatch 更新所有DrawCall

如果出现了WaitingForJob或PutGeometryJobFence,则说明合并网格开销很大

优化合理应该消失

 

一个Canvas一个网格,注意拆分Canvas,尽量动静分离

                                                                                                                              

Z一定要调为0,除非有3DUI穿插。

 

Image为null或者alpha为0不能降低开销,Image为null还会不能合并

 

Item类型,如果当前图标和相邻图标(非当下图标)有重叠,那么则不会合并为2个drawcall;

这时尽量改hierarchy里面的排序,并可根据item内的层级(background,icon等)顺序,来添加父类,对每一个层级进行管理,而不是每一个item;(添加方法来进行管理,存储还是按照item的list来管理,//添加管理类

 

当某一个item类型处于选中,播放动画等状态,并且所处canvas下内容比较多的情况下,可以单独添加方法,给他自己添加一个canvas,取消选中时则remove掉,(写到UIGameUtil),用于动静分离,

借鉴

Mask是能少用就少用,等于一个跟其他合并不了的完全独立的,增加的远不止几个drawcall;


界面内(如背包)图标相互不要重叠,会增加不必要的drawcall

 

如背包等,如果前面图标能完全遮挡后面图标,且后面图标为sliced模式,可把fill Center改为true;目前项目大部分图标过小或中间有透明,无法优化,优先可优化类型(边框,中间镂空)

 

空image,去网页看

拆分canvas,,血条伤害等单给个canvas(如果当前canvas下其他东西也不少的话)

//血条等设置最小移动阈值,并且设定更新频率

 

 

增加小数值判断,不大于一个数值不做改变,降低消耗

TextMeshPro,适合静态(目前予以否认状态,字体库太大,不值,而且只适用于静态,并且不容易通过配置来改变)

 

动态文字尽量不用outLine

 

两个UI有一个需要隐藏的,可以在摄像机上设置一个层级,不渲染,当需要隐藏的时候,直接修改layer,

 

两层UI,可看见后面的时候,可直接把后面渲染成一个rendererTexture;(写个插件!!!)

思路1:截图截UI全屏,然后挂在image上,关闭时删除

思路2:单新建一个相机做渲染。

具体损耗等待测试来确定方案

 

//用于全屏遮挡检测,(tips等),降低overDraw,以下为代码

using UnityEngine;

using System.Collections;

 

namespace UnityEngine.UI

{

    public classEmpty4Raycast : MaskableGraphic

    {

        protectedEmpty4Raycast()

        {

           useLegacyMeshGeneration = false;

        }

 

        protectedoverride void OnPopulateMesh(VertexHelper toFill)

        {

           toFill.Clear();

        }

    }

}

事件检测优化,会遍历canvas下所有image,text等组件,浪费,目前思路,重写raycast选项开启关闭,增加一个list管理,开启调用add,关闭则remove,只遍历list内组件

 

大量颜色渐变的时候,可以改变材质球的tintcolor来控制,个人认为一两个的没有必要单弄个材质球,若大量可用;更主要用途,通过动画来控制tintcolor的变化.

 

 

拆分一下现在的层级分类,其他还好,底层静态的,把joystick单独拆出去,太频繁变化了然后上面的金币,不过目前主城还好,毕竟只有两个比较小的界面,战斗目前基本都存在各种变化

摇杆(单拆);

伤害(单拆,并且颜色渐变等还可优化,借鉴上面)

技能(单拆)

连击(单拆)

血条等(单拆血条等有变化的,其他不变)

 

动画,播完没用就关,有用再开,增加父类控制(直接写到动画插件里)

 

然后增加一个用定点数换取渲染填充率的脚本,个人目前仅认为用于不规则按钮重叠问题比较实用,其他方面图集可用,需要实践,另用于很大的不规则图形,空白区域很多的情况下,脚本目前还未测试(准备与选关界面结合使用,完善选关界面的不规则图形检测规则来测试)

using System.Collections.Generic;

 

namespace UnityEngine.UI

{

    [AddComponentMenu("UI/Effects/PolygonImage",16)]

   [RequireComponent(typeof(Image))]

    public classPolygonImage : BaseMeshEffect

    {

        protectedPolygonImage()

        { }

 

        // GCFriendly

        privatestatic Vector3[] fourCorners = new Vector3[4];

        privatestatic UIVertex vertice = new UIVertex();

        privateRectTransform rectTransform = null;

        privateImage image = null;

        publicoverride void ModifyMesh(VertexHelper vh)

        {

            if(!isActiveAndEnabled) return;

 

            if(rectTransform == null)

            {

               rectTransform = GetComponent();

            }

            if(image == null)

            {

               image = GetComponent();

            }

            if(image.type != Image.Type.Simple)

            {

               return;

            }

            Spritesprite = image.overrideSprite;

            if(sprite == null || sprite.triangles.Length == 6)

            {

                //only 2 triangles

               return;

            }

 

            //Kanglai: at first I copy codes from Image.GetDrawingDimensions

            // tocalculate Image's dimensions. But now for easy to read, I just take usage ofcorners.

            if(vh.currentVertCount != 4)

            {

               return;

            }

 

           rectTransform.GetLocalCorners(fourCorners);

 

            //Kanglai: recalculate vertices from Sprite!

            int len= sprite.vertices.Length;

            varvertices = new List(len);

            Vector2Center = sprite.bounds.center;

            Vector2invExtend = new Vector2(1 / sprite.bounds.size.x, 1 / sprite.bounds.size.y);

            for(int i = 0; i < len; i++)

            {

                // normalize

               float x = (sprite.vertices[i].x - Center.x) * invExtend.x + 0.5f;

               float y = (sprite.vertices[i].y - Center.y) * invExtend.y + 0.5f;

                //lerp to position

               vertice.position = new Vector2(Mathf.Lerp(fourCorners[0].x,fourCorners[2].x, x), Mathf.Lerp(fourCorners[0].y, fourCorners[2].y, y));

               vertice.color = image.color;

               vertice.uv0 = sprite.uv[i];

               vertices.Add(vertice);

            }

 

            len =sprite.triangles.Length;

            vartriangles = new List(len);

            for(int i = 0; i < len; i++)

            {

               triangles.Add(sprite.triangles[i]);

            }

 

           vh.Clear();

            vh.AddUIVertexStream(vertices,triangles);

        }

    }

}

 

TextBest Fit选项能不用就不要用,自己来限制;

 

-Alpha:这个选项很多组件都有,用处也是一样的,在美术中,这个叫做Alpha通道的东东是用来控制透明度的,他的值从0到1.0是完全透明,1是完全不透明;

-Interactable确认该组件是否接受输入,当他被设置为false时,交互功能将被禁用;

-BlockRaycasts是否让该组件像collider一样接受射线检测?你需要在依赖于Canvas的图形射线检测者上唤醒射线检测方法。这个不会作用于Physics.Raycast;

-IgnoreParent Groups(忽略父级团)是否响应父级group的方法

 

细节:

CanvasGroup的经典使用:

-在窗口的GameObject上添加一个CanvasGroup,通过控制它的Alpha值来淡入或淡出整个窗口;

-通过给父级GameObject添加一个CanvasGroup并设置它的Interactable值为false来制作一整套没有交互(灰色)的控制;

 

-通过将元素或元素的一个父级添加CanvasGroup并设置BlockRaycasts值为false来制作一个或多个不阻止鼠标事件的UI元素

 

总结:

优化方向1:动态和静态分离,保证动态刷新时不去改变静态里面的内容;

优化方向2:界面重叠时,尽量消除在当前显示界面后面的那些渲染不到的界面的影响;

            1:界面控制,把后面用不到的界面暂时隐藏(active或alphagroup,根据需求)2:在后面界面不会发生改变的情况下,(如弹出tips,tips后面的内容不会发生改变时),把后面的整个界面渲染成rendereTexture,然后隐藏界面,来降低损耗

优化方向3: 界面内子item类型避免重叠,如必须,降低其所造成的损耗(如分层管理等,看看是否可以用fillcenter),根据需求来优化,检查网格是否过高;

优化方向4:频率过高导致的损耗:1.设置频率

                                                2.设置最小改变的阈值

优化方向5:事件检测优化(用一个空Text来检测目前用的不少,tips之类的),全部改为上面的方法;

 

你可能感兴趣的:(关于UGUI的个人优化总结)