Unity 之 UGUI 小總結(jié)

?? 開發(fā)過程中對UGUI的一個小總結(jié)房揭。

?? 首先從原畫師拿到效果圖棚瘟,美術切圖,拿到碎圖后打成大圖吟孙。

? ? 我們先來說一下圖:RGBA8888:每一個通道占8位。大圖:1024*1024聚蝶。高端??? 機:2048*2048杰妓。

?? 我們通常從美工那里拿來碎圖,歪歪使用的一個工具texturepacker 把碎圖打成大圖碘勉,導出成 .tpsheet? .png格式稚失。其次我們要做的是,在Unity3d中導入插件texture import(此插件會自動把大圖打成圖集).然后把大圖導入U3D恰聘。

? 在UI優(yōu)化中較為明顯而眾所周知的就是降低DrawCall(注釋:DrawCall CPU向GPU發(fā)送的一次渲染指令)。而降低DrawCall我們會采用靜態(tài)合批和動態(tài)合批吸占。(注釋:合批必須同類型 Mesh 同材質(zhì)晴叨。)DrawCall的標準 RGP 類 小于 150。

?? 然而矾屯,工作中我們優(yōu)化大概分為UI層級計算兼蕊,UI重建和多層級渲染。接下來我們來說一下:

UI層級 計算 :

1件蚕,計算層級:

1,如果有一個UI元素孙技,它所占的屏幕范圍內(nèi)(通常是矩形)产禾,如果沒有任何UI在它的底下,那么它的層級號就是0(最底下)牵啦;

2,如果有一個UI在其底下且該UI可以和它Batch亚情,那它的層級號與底下的UI層級一樣;

3,如果有一個UI在其底下但是無法與它Batch哈雏,那它的層級號為底下的UI的層級+1楞件;

4,如果有多個UI都在其下面,那么按前兩種方式遍歷計算所有的層級號裳瘪,其中最大的那個作為自己的層級號土浸。

合并批次原則;

同層級{同材質(zhì)球,}

{0 : { image ??, image, text ?}}

1,Unity會將每一層的所有元素進行一個排序(按照材質(zhì)彭羹、紋理等信息)黄伊,合并掉可以Batch的元素成為一個批次

2,Text組件會排在Image組件之前渲染。

3,派殷,Unity會再做一個優(yōu)化还最,即如果相鄰間的兩個批次正好可以Batch的話就會進行Batch(這么處理,可以合成一個批次愈腾,如下:)

{0 : { text ??image ?}}textàimage

{1 : { text ?,image }}

0: textàimage ???1: textàimage

下面我們來看一個列子憋活,這樣會更加的清晰:

一個層級為0的ImageA,一個層級為1的ImageB(2個Image可Batch)和一個層級為0的TextC虱黄,

textCàimageAàimageB

一個層級為0的TextD悦即,一個層級為1的TextE(2個Text可Batch)和一個層級為0的ImageF,

0 : textD –>imageFà1 : textEàimage h ???3:

0 : textD –>imageFà1 : textEàimage h

總結(jié):

1,有相同材質(zhì)和紋理的UI元素是可以Batch的橱乱,可以Batch的UI上下疊在一塊不會影響性能辜梳,但是如果不能Batch的UI元素疊在一塊昵济,就會增加Drawcall開銷

2,盡量讓同一個材質(zhì)球上的東西 放在同一級上

3,有些情況可以考慮人為增加層級從而減少Drawcall乏沸,比如一個Text的層級為0,另一個可Batch的Text疊在一個圖片A上桐愉,層級為1危纫,那此時2個Text因為層級不同會安排2個Drawcall宗挥,但如果在第一個Text下放一個透明的圖片(與圖片A可Batch),那兩個Text的層級就一致了种蝶,Drawcall就可以減少一個契耿。

Text0 –》Imageàtext 1

4,應該盡量避免使用Mask,其實Mask的功能有些時候可以變通實現(xiàn)螃征,比如設計一個邊框搪桂,讓這個邊框疊在最上面,底下的UI移動時盯滚,就會被這個邊框遮滋咝怠酗电;

5, z值 保持為0

UI重建:

1,動靜分離:

經(jīng)常發(fā)生變動的ui單獨放在一個Canvase

2内列,刪除不必要的元素撵术。

3,CanvasRender.setDisable .

4德绿,Text的Best Fit選項.

5,Canvas的Pixel Perfect選項

6,使用緩存池來保存ScrollView中的Item,對于移出或移進View外的的元素荷荤,不要調(diào)用disable或enable,而是把它們放到緩存池里或從緩存池中取出復用。

7, 除了rebuild過程之外移稳,UGUI的touch處理消耗也可能會成為性能熱點蕴纳。因為UGUI在默認情況下會對所有可見的Graphic組件調(diào)用raycast。對于不需要接收touch事件的grahic个粱,一定要禁用raycast古毛。對于unity5以上的可以關閉graphic的Raycast Target而對于unity4.6,可以給不需要接收touch的UI元素加上canvasgroup組件都许。

多層級渲染:

1,canvasRender .setdisable()

2,只掛載button替代 ?空的image

3稻薇,不要使用空的Image,在Unity中,RayCast使用Graphi作為基本元素來檢測touch,在筆者參與的項目中胶征,很多同學使用空的image并將alpha設置為0來接收touch事件塞椎,這樣會產(chǎn)生不必要的overdraw。通過如下類NoDrawingRayCast來接收事件可以避免不必要的overdraw睛低。

3. public class NoDrawingRayCast : Graphic

4. {

5. ? ? public override void SetMaterialDirty()

6. ? ? {

7. ? ? }

8. ? ? public override void SetVerticesDirty()

9. ? ? {

10. ? ? }

11. ? ? protected override void OnFillVBO(List vbo)

12. ? ? {

13. ? ? ? ? vbo.Cslear();

14. ? ? }

}

性能檢測工具:

1profile

常見問題:

Q1:我在UGUI里更改了Image的Color屬性案狠,那么Canvas是否會重建?我只想借用它的Color做Animation里的變化量钱雷。

如果修改的是Image組件上的Color屬性骂铁,其原理是修改頂點色,因此是會引起網(wǎng)格的Rebuild的(即Canvas.BuildBatch操作罩抗,同時也會有Canvas.SendWillRenderCanvases的開銷)拉庵。而通過修改頂點色來實現(xiàn)UI元素變色的好處在于,修改頂點色可以保證其材質(zhì)不變套蒂,因此不會產(chǎn)生額外的Draw Call钞支。

Q2:Unity自帶的UI Shader處理顏色時,改_Color屬性不會觸發(fā)頂點重建嗎?

在UI的默認Shader中存在一個Tint Color的變量操刀,正常情況下伸辟,該值為常數(shù)(1,1,1),且并不會被修改馍刮。如果是用腳本訪問Image的Material,并修改其上的Tint Color屬性時窃蹋,對UI元素產(chǎn)生的網(wǎng)格信息并沒有影響卡啰,因此就不會引起網(wǎng)格的Rebuild静稻。但這樣做因為修改了材質(zhì),所以會增加一個Draw Call匈辱。

Q:動靜分離或者多Canvas帶來性能提升的理論基礎是什么呢振湾?如果靜態(tài)部分不變動,整個Canvas就不刷新了亡脸?

在UGUI中押搪,網(wǎng)格的更新或重建(為了盡可能合并UI部分的DrawCall)是以Canvas為單位的,且只在其中的UI元素發(fā)生變動(位置浅碾、顏色等)時才會進行大州。因此,將動態(tài)UI元素與靜態(tài)UI元素分離后垂谢,可以將動態(tài)UI元素的變化所引起的網(wǎng)格更新或重建所涉及到的范圍變小厦画,從而降低一定的開銷。而靜態(tài)UI元素所在的Canvas則不會出現(xiàn)網(wǎng)格更新和重建的開銷滥朱。

Q:UWA建議“盡可能將靜態(tài)UI元素和頻繁變化的動態(tài)UI元素分開根暑,存放于不同的Panel下。同時徙邻,對于不同頻率的動態(tài)元素也建議存放于不同的Panel中排嫌。”那么請問缰犁,如果把特效放在Panel里面淳地,需要把特效拆到動態(tài)的里面嗎?

通常特效是指粒子系統(tǒng)民鼓,而粒子系統(tǒng)的渲染和UI是獨立的薇芝,僅能通過Render Order來改變兩者的渲染順序,而粒子系統(tǒng)的變化并不會引起UI部分的重建丰嘉,因此特效的放置并沒有特殊的要求夯到。

Q:多人同屏的時候,人物移動會使得頭頂上的名字Mesh重組饮亏,從而導致較為嚴重的卡頓耍贾,請問一下是否有優(yōu)化的辦法?

如果是用UGUI開發(fā)的路幸,當頭頂文字數(shù)量較多時荐开,確實很容易引起性能問題,可以考慮從以下幾點入手進行優(yōu)化:

1.盡可能避免使用UI/Effect简肴,特別是Outline晃听,會使得文本的Mesh增加4倍,導致UI重建開銷明顯增大;

2.拆分Canvas能扒,將屏幕中所有的頭頂文字進行分組佣渴,放在不同的Canvas下,一方面可以降低更新的頻率(如果分組中沒有文字移動初斑,該組就不會重建)辛润,另一方面可以減小重建時涉及到的Mesh大小(重建是以Canvas為單位進行的)见秤;

3.降低移動中的文字的更新頻率砂竖,可以考慮在文字移動的距離超過一個閾值時才真正進行位移,從而可以從概率上降低Canvas更新的頻率鹃答。

三乎澄、界面切換

Q1:游戲中出現(xiàn)UI界面重疊,該怎么處理較好挣跋?比如當前有一個全屏顯示的UI界面三圆,點其中一個按鈕會再起一個全屏界面,并把第一個UI界面蓋住避咆。我現(xiàn)在的做法是把被覆蓋的界面SetActive(False)舟肉,但發(fā)現(xiàn)后續(xù)SetActive(True)的時候會有GC.Alloc產(chǎn)生。這種情況下查库,希望既降低Batches又降低GC Alloc的話路媚,有什么推薦的方案嗎?

可以嘗試通過添加一個Layer如OutUI樊销, 且在Camera的Culling Mask中將其取消勾選(即不渲染該Layer)整慎。從而在UI界面切換時,直接通過修改Canvas的Layer來實現(xiàn)“隱藏”围苫。但需要注意事件的屏蔽裤园,禁用動態(tài)的UI元素等等。

這種做法的優(yōu)點在于切換時基本沒有開銷剂府,也不會產(chǎn)生多余的Draw Call拧揽,但缺點在于“隱藏時”依然還會有一定的持續(xù)開銷(通常不太大),而其對應的Mesh也會始終存在于內(nèi)存中(通常也不太大)腺占。

以上的方式可供參考淤袜,而性能影響依舊是需要視具體情況而定。

Q2:通過移動位置來隱藏UI界面衰伯,會使得被隱藏的UIPanel繼續(xù)執(zhí)行更新(LateUpdate有持續(xù)開銷)铡羡,那么如果打開的界面比較多,CPU的持續(xù)開銷是否就會超過一次SetActive所帶來的開銷意鲸?

這確實是需要注意的烦周,通過移動的方式“隱藏”的UI界面只適用于幾個切換頻率最高的界面尽爆,另外,如果“隱藏”的界面持續(xù)開銷較高读慎,可以考慮只把一部分Disable教翩,這個可能就需要具體看界面的復雜度了。一般來說在沒有UI元素變化的情況下贪壳,持續(xù)的Update開銷是不太明顯的。

Q3:如圖蚜退,我們在UI打開或者移動到某處的時候經(jīng)常會觀測到CPU上的沖激闰靴,經(jīng)過進一步觀察發(fā)現(xiàn)是因為Instantiate產(chǎn)生了大量的GC。想請問下Instantiate是否應該產(chǎn)生GC呢钻注?我們能否通過資源制作上的調(diào)整來避免這樣的GC呢蚂且?如下圖,因為一次性產(chǎn)生若干MB的GC在直觀感受上還是很可觀的幅恋。


準確的說這些GC Alloc并不是由Instantiate直接引起的杏死,而是因為被實例化出來的組件會進行OnEnable操作,而在OnEnable操作中產(chǎn)生了GC捆交,比如以上圖中的函數(shù)為例:

上圖中的Text.OnEnable是在實例化一個UI界面時淑翼,UI中的文本(即Text組件)進行了OnEnable操作,其中主要是初始化文本網(wǎng)格的信息(每個文字所在的網(wǎng)格頂點品追,UV玄括,頂點色等等屬性),而這些信息都是儲存在數(shù)組中(即堆內(nèi)存中)肉瓦,所以文本越多遭京,堆內(nèi)存開銷越大。但這是不可避免的泞莉,只能盡量減少出現(xiàn)次數(shù)哪雕。

因此,我們不建議通過Instantiate/Destroy來處理切換頻繁的UI界面鲫趁,而是通過SetActive(true/false)斯嚎,甚至是直接移動UI的方式,以避免反復地造成堆內(nèi)存開銷饮寞。

四孝扛、加載相關

Q1:UGUI的圖集操作中我們有這么一個問題,加載完一張圖集后幽崩,使用這個方式獲取其中一張圖的信息:assetBundle.Load (subFile, typeof (Sprite)) as Sprite;這樣會復制出一個新貼圖(圖集中的子圖)苦始,不知道有什么辦法可以不用復制新的子圖,而是直接使用圖集資源 慌申。


經(jīng)過測試陌选,這確實是Unity在4.x版本中的一個缺陷理郑,理論上這張“新貼圖(圖集中的子圖)”是不需要的,并不應該加載咨油。 因此您炉,我們建議通過以下方法來繞過該問題:

在assetBundle.Load (subFile, typeof (Sprite)) as Sprite;之后,調(diào)用

Texture2D t = assetBundle.Load (subFile, typeof (Texture2D)) as Texture2D;

Resources.UnloadAsset(t);

從而卸載這部分多余的內(nèi)存役电。

Q2:加載UI預制的時候赚爵,如果把特效放到預制里,會導致加載非常耗時法瑟。怎么優(yōu)化這個加載時間呢冀膝?

UI和特效(粒子系統(tǒng))的加載開銷在多數(shù)項目中都占據(jù)較高的CPU耗時。UI界面的實例化和加載耗時主要由以下幾個方面構成:

紋理資源加載耗時

UI界面加載的主要耗時開銷霎挟,因為在其資源加載過程中窝剖,時常伴有大量較大分辨率的Atlas紋理加載,我們在之前的Unity加載模塊深度分析之紋理篇有詳細講解酥夭。對此赐纱,我們建議研發(fā)團隊在美術質(zhì)量允許

1,1024*768 ???1024*1024

2, 640*480 ?????512*512

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市熬北,隨后出現(xiàn)的幾起案子疙描,更是在濱河造成了極大的恐慌,老刑警劉巖蒜埋,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件淫痰,死亡現(xiàn)場離奇詭異,居然都是意外死亡整份,警方通過查閱死者的電腦和手機待错,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來烈评,“玉大人火俄,你說我怎么就攤上這事〗补冢” “怎么了瓜客?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竿开。 經(jīng)常有香客問我谱仪,道長,這世上最難降的妖魔是什么否彩? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任疯攒,我火速辦了婚禮,結(jié)果婚禮上列荔,老公的妹妹穿的比我還像新娘敬尺。我一直安慰自己枚尼,他們只是感情好,可當我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布砂吞。 她就那樣靜靜地躺著署恍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蜻直。 梳的紋絲不亂的頭發(fā)上盯质,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天,我揣著相機與錄音概而,去河邊找鬼唤殴。 笑死,一個胖子當著我的面吹牛到腥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔚袍,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼乡范,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了啤咽?” 一聲冷哼從身側(cè)響起晋辆,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎宇整,沒想到半個月后瓶佳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡鳞青,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年霸饲,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片臂拓。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡厚脉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出胶惰,到底是詐尸還是另有隱情傻工,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布孵滞,位于F島的核電站中捆,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏坊饶。R本人自食惡果不足惜泄伪,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幼东。 院中可真熱鬧臂容,春花似錦科雳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至球散,卻和暖如春尿赚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蕉堰。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工凌净, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屋讶。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓冰寻,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皿渗。 傳聞我的和親對象是個殘疾皇子斩芭,可洞房花燭夜當晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容