Unity 優(yōu)化之UGUI(uwa_UGUI優(yōu)化直播總結(jié))

鏈接1:Unity 優(yōu)化之UGUI (2017年版【一】) - 簡(jiǎn)書(shū)

鏈接2:UGUI 降低填充率技巧兩則 - UWA Blog

視頻地址:https://v.qq.com/x/page/l0329fvbrfn.html

盡可能的讓UI元素合批

首先創(chuàng)建一個(gè)新的場(chǎng)景,攝像camera為Solod Color

image
image

可以看到場(chǎng)景中的Barches為1,這是因?yàn)閏amera在做Clear操作

?

image

然后創(chuàng)建兩個(gè)Button 去掉對(duì)應(yīng)的Text,運(yùn)行unity發(fā)現(xiàn)產(chǎn)生的Batches變?yōu)?

?

image

當(dāng)兩個(gè)Button進(jìn)行重疊的是時(shí)候,Batches并沒(méi)有變化

?

image

但是對(duì)有Text的兩個(gè)Button進(jìn)行上面的操作,就會(huì)出現(xiàn)不一樣的效果,重疊后的Batches和未重疊Batches不一致

?

image

?

image

按照公開(kāi)課中的說(shuō)法,這種重疊的做法會(huì)打破原有的拓?fù)渑判颍═ext2 與Button2合并),造成Draw Call的合并失敗(Text -Button -Text - Button),當(dāng)然在Hierarchy視圖中也要盡量按照這種拓?fù)渑判虻姆绞竭M(jìn)行UI的層級(jí)擺放。

結(jié)論:在進(jìn)行UI設(shè)計(jì)額時(shí)候盡量少使用來(lái)自不同Atlas的材質(zhì),也盡量避免這種傾軋的情況(Scene視圖調(diào)節(jié)為Writeframe模式可以更容易查看),盡可能把所有的文字放到圖片之上,使用同種字體,更容易進(jìn)行合批

?

image

接下來(lái)要說(shuō)的就是Mask組件

在一個(gè)新的場(chǎng)景中放圖兩個(gè)Image,然后設(shè)置統(tǒng)一的Packing Tag

?

image

而且也要在Editor Settings開(kāi)啟圖集選項(xiàng)

?

image

運(yùn)行前后對(duì)應(yīng)可發(fā)現(xiàn)兩張圖片進(jìn)行了合批

?

image

?

image

然后在場(chǎng)景中添加一個(gè)對(duì)應(yīng)的Mask,發(fā)現(xiàn)Batches有所變化,兩個(gè)圖片也進(jìn)行了合批

?

image

把其中一個(gè)圖片放到mask的遮罩中,發(fā)現(xiàn)圖片無(wú)法合批

?

image

結(jié)論: 首先一個(gè)Mask組件就會(huì)產(chǎn)生一個(gè)Draw Call,而且在Mask中的圖片無(wú)法與外界的圖片進(jìn)行合批

減少Overdraw

?

image

根據(jù)上圖的顯示,調(diào)節(jié)到OverDraw模式,顏色越鮮亮的地方造成的OverDraw越大,隨之帶來(lái)的GPU壓力也是越大的

下面來(lái)說(shuō)減少OverDraw的一些策略

在ImageType選項(xiàng)為Sliced的情況下,不需要Fill Center 的時(shí)候去掉勾選

?

image

作者錢康來(lái)重寫Image相關(guān)組件降低性能消耗

Code Empty4Raycast


using UnityEngine;
using System.Collections;

namespace UnityEngine.UI
{
    public class Empty4Raycast : MaskableGraphic
    {
        protected Empty4Raycast()
        {
            useLegacyMeshGeneration = false;
        }

        protected override void OnPopulateMesh(VertexHelper toFill)
        {
            toFill.Clear();
        }
    }
}

Code Code PolygonImage


using System.Collections.Generic;

namespace UnityEngine.UI
{
    [AddComponentMenu("UI/Effects/PolygonImage", 16)]
    [RequireComponent(typeof(Image))]
    public class PolygonImage : BaseMeshEffect
    {
        protected PolygonImage()
        { }

        // GC Friendly
        private static Vector3[] fourCorners = new Vector3[4];
        private static UIVertex vertice = new UIVertex();
        private RectTransform rectTransform = null;
        private Image image = null;
        public override void ModifyMesh(VertexHelper vh)
        {
            if (!isActiveAndEnabled) return;

            if (rectTransform == null)
            {
                rectTransform = GetComponent<RectTransform>();
            }
            if (image == null)
            {
                image = GetComponent<Image>();
            }
            if (image.type != Image.Type.Simple)
            {
                return;
            }
            Sprite sprite = image.overrideSprite;
            if (sprite == null || sprite.triangles.Length == 6)
            {
                // only 2 triangles
                return;
            }

            // Kanglai: at first I copy codes from Image.GetDrawingDimensions
            // to calculate Image's dimensions. But now for easy to read, I just take usage of corners.
            if (vh.currentVertCount != 4)
            {
                return;
            }

            rectTransform.GetLocalCorners(fourCorners);

            // Kanglai: recalculate vertices from Sprite!
            int len = sprite.vertices.Length;
            var vertices = new List<UIVertex>(len);
            Vector2 Center = sprite.bounds.center;
            Vector2 invExtend = 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;
            var triangles = new List<int>(len);
            for (int i = 0; i < len; i++)
            {
                triangles.Add(sprite.triangles[i]);
            }

            vh.Clear();
            vh.AddUIVertexStream(vertices, triangles);
        }
    }
}

減少Raycast Target

在對(duì)應(yīng)的Text Image和Rawimage中都有Raycast Target選項(xiàng),這個(gè)選項(xiàng)負(fù)責(zé)接收我們所點(diǎn)擊的事件,但是項(xiàng)目中我們有些UI元素是不需要這些東西,所有可以去掉,減少不必要的性能消耗,可以用RaycastTarget檢測(cè)小工具,他可以在對(duì)應(yīng)的editor模式下,把開(kāi)啟Raycast Target選項(xiàng)的UI以藍(lán)色線框的形式顯示出來(lái),方便大家檢查遺漏的關(guān)閉的UI元素

?

image

避免網(wǎng)格重建(Canvas.BuildBatch)

?

image

Canvas.BuildBatch

現(xiàn)在untiy2017版本中Canvas.BuildBatch的主要耗時(shí)已經(jīng)放到了多線程中

網(wǎng)格重建的意思是把Canvas下所有的ui合成一個(gè)Mesh,當(dāng)有UI元素更改的時(shí)候就會(huì)重建這個(gè)Mesh,造成性能消耗。 采取的對(duì)應(yīng)策略就是【動(dòng)靜分離】,在經(jīng)常變動(dòng)的UI元素(位置、顏色、圖片等)上添加Canvas組件,就可以避免因?yàn)閁I的改變?cè)斐烧麄€(gè)Mesh全部重建。當(dāng)然對(duì)于數(shù)量較多需要進(jìn)行顏色漸變的UI元素都添加上canvas顯然不合適,因?yàn)樘砑觕anvas會(huì)增加DrawCall。所以我們需要采用另一個(gè)策略,在Image上添加一個(gè)自定義的material,然后更改這個(gè)material的Tint屬性,這樣既能滿足顏色漸變,又能避免網(wǎng)格頻繁重建造成的性能消耗(實(shí)質(zhì)是避免修改網(wǎng)格上的頂點(diǎn)屬性,造成網(wǎng)格重建)

?

image

?

image

?

image

額外注意的地點(diǎn)

避免使用OutLine組件

避免使用Shadow組件

應(yīng)對(duì)策略:使用Text Mesh Pro插件是一個(gè)不錯(cuò)的選擇(現(xiàn)在已經(jīng)免費(fèi))

避免頻繁使UI元素SetActive(開(kāi)、關(guān)),會(huì)造成網(wǎng)格重建

減少Raycast Target

在對(duì)應(yīng)的Text Image和Rawimage中都有Raycast Target選項(xiàng),這個(gè)選項(xiàng)負(fù)責(zé)接收我們所點(diǎn)擊的事件,但是項(xiàng)目中我們有些UI元素是不需要這些東西,所有可以去掉,減少不必要的性能消耗,可以用RaycastTarget檢測(cè)小工具,他可以在對(duì)應(yīng)的editor模式下,把開(kāi)啟Raycast Target選項(xiàng)的UI以藍(lán)色線框的形式顯示出來(lái),方便大家檢查遺漏的關(guān)閉的UI元素

?

image

避免網(wǎng)格重建(Canvas.BuildBatch)

?

image

Canvas.BuildBatch

現(xiàn)在untiy2017版本中Canvas.BuildBatch的主要耗時(shí)已經(jīng)放到了多線程中

網(wǎng)格重建的意思是把Canvas下所有的ui合成一個(gè)Mesh,當(dāng)有UI元素更改的時(shí)候就會(huì)重建這個(gè)Mesh,造成性能消耗。 采取的對(duì)應(yīng)策略就是【動(dòng)靜分離】,在經(jīng)常變動(dòng)的UI元素(位置、顏色、圖片等)上添加Canvas組件,就可以避免因?yàn)閁I的改變?cè)斐烧麄€(gè)Mesh全部重建。當(dāng)然對(duì)于數(shù)量較多需要進(jìn)行顏色漸變的UI元素都添加上canvas顯然不合適,因?yàn)樘砑觕anvas會(huì)增加DrawCall。所以我們需要采用另一個(gè)策略,在Image上添加一個(gè)自定義的material,然后更改這個(gè)material的Tint屬性,這樣既能滿足顏色漸變,又能避免網(wǎng)格頻繁重建造成的性能消耗(實(shí)質(zhì)是避免修改網(wǎng)格上的頂點(diǎn)屬性,造成網(wǎng)格重建)

?

image

?

image

?

image

額外注意的地點(diǎn)

避免使用OutLine組件

避免使用Shadow組件

應(yīng)對(duì)策略:使用Text Mesh Pro插件是一個(gè)不錯(cuò)的選擇(現(xiàn)在已經(jīng)免費(fèi))

避免頻繁使UI元素SetActive(開(kāi)、關(guān)),會(huì)造成網(wǎng)格重建

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容