概述NGUI:在遠古時期,UGUI出現(xiàn)之前,約國內(nèi)八成左右的商業(yè)項目,UI都是使用NGUI來實現(xiàn)的,可以說NGUI是元老了。
UGUI:從Unity4.6版本開始官方推出了UGUI。UGUI是Unity 官方的UI系統(tǒng),在兼容性和官方支持上來說,官方的 UI系統(tǒng)具有一定優(yōu)勢。
八卦一下:NGUI和UGUI的作者是同一個人,ArenMook(后來又因個人原因已從Unity離職)。 NGUI和UGUI之元素更新NGUI元素更新: 查看NGUI的源碼,發(fā)現(xiàn)NGUI的UIPanel采用的是調(diào)用LateUpdate的方式進行更新。每幀都會調(diào)用UpdateSelf,做的事情就是更新當前UIPanel內(nèi)所有組件的位置、圖層關(guān)系、甚至重建信息。值得指出的是,因為是每幀執(zhí)行,即使UI沒有任何改變,是靜態(tài)的UI仍然會有一定的開銷。 ![]() UGUI元素更新: 查看UGUI的源碼,發(fā)現(xiàn)UGUI已經(jīng)不是通過每幀調(diào)用來產(chǎn)生更新了。而是通過Canvas.SendWillRenderCanvas添加全局委托,再通過m_LayoutRebuildQueue和m_GraphicRebuildQueue,這兩個隊列分別記錄Layout和外觀發(fā)生變化的UI元素。在渲染前,會在這個回調(diào)函數(shù)里去處理這兩個隊列里的元素,分別進行Rebuild。因此,如果在UGUI中如果UI元素是靜態(tài)的,則不會有持續(xù)開銷。 ![]() 優(yōu)化策略: NGUI中可直接通過Color.alpha = 0去隱藏。這樣UI元素的頂點數(shù)可被移除掉,也可避免掉SetActive的開銷。 注意!不能用Scale = 0 ,這僅僅把網(wǎng)格Scale為0,但頂點數(shù)還在,DC依舊存在。 UGUI中設(shè)置Scale = 0,或者添加 Canvas Group 組件設(shè)置Alpha = 0,這兩種均可去掉元素的頂點,也可避免SetActive的開銷。 注意!UGUI中不能使用Color.alpha = 0 這種方式,因為這相當于貼了一個透明面片還是會被畫到場景中,對DC和OverDraw無影響。 NGUI和UGUI之Drawcall合批( Batch )NGUI是通過手動調(diào)整Depth值,根據(jù)值的大小以UIPanel為單位進行一個排序,Depth接近,中間沒有材質(zhì)不同的對象打斷時,相同材質(zhì)的對象進行合批。注意在實際調(diào)整UIPanel的Depth時,請將動態(tài)文本單獨設(shè)置一個Depth,如果有動效則分別單獨設(shè)置其Depth,然后再將相同材質(zhì)的UI分別設(shè)置為同一個Depth。 ![]() UGUI的合批規(guī)則,則是自動計算元素的層級 1.首先排除掉active=false,scale=0,Canvas Group=0 2.遍歷所有元素,根據(jù)包圍盒重疊關(guān)系分組 3.根據(jù)圖層順序得到depth,最下面的元素為depth=0,依次往上遞增=1,=2,=n 4.同一分組,根據(jù)圖層的順序,如相鄰depth的元素是同一材質(zhì)的對象時,進行合批處理。 5.特別要注意下圖所示情況,因為分組是根據(jù)包圍盒重疊來判斷的,下圖上半部分,被判斷為2個分組,因為他們所屬不同材質(zhì),所以產(chǎn)生了七個drawcall,而下半部分,因為是1個分組,所以只有4個drawcall。這點是在UGUI里需要特別注意的。 ![]() NGUI和UGUI之網(wǎng)格更新NGUI中Batch是以UIPanel為單位來改變的,UIPanel內(nèi)單個元素變化則FillDrawCall 即更新單個DrawCall,如果發(fā)生重建Rebuild,則 FillAllDrawCall 更新所有DrawCall。值得特別注意的NGUI的網(wǎng)格更新是每幀進行的,在元素更新時已經(jīng)說過。 ![]() UGUI的話,因為網(wǎng)格重建的實現(xiàn)是在C++里實現(xiàn)的(因此網(wǎng)格合并比NGUI要快),所以不能找到其源碼來分析下,但是不影響分析出其更新原理。 在 UGUI 中,Batch是以Canvas為單位的,即在同一個Canvas下的UI元素最終都會被Batch到同一個Mesh中。而在Batch前,UGUI會根據(jù)這些元素的材質(zhì),以及渲染順序進行分組重排,根據(jù)分組將相鄰depth并且相同材質(zhì)的UI元素合并在同一個SubMesh中,從而把DrawCall降到最低。而Batch的操作只會在UI元素發(fā)生變化時才進行,且合成的Mesh越大,操作的耗時也就越大。 因此,我們建議盡可能把頻繁變化(位置,縮放,旋轉(zhuǎn),顏色等)的UI元素從復(fù)雜的面板中(UIPanel/Canvas)分離出來,放到獨立的面板里面,從而避免頻繁重建,也就是所謂的動靜分離。 優(yōu)化界面的技巧看完這兩套UI的更新原理、合批機制和網(wǎng)格更新方式。那么降低界面渲染的技巧,其實也就變成了如何降低UI中產(chǎn)生的Drawcall,讓更新的網(wǎng)格降低的技巧。 1.盡可能的把頻繁變化(位置,縮放,旋轉(zhuǎn),顏色等)的UI元素從復(fù)雜的面板中(UIPanel/Canvas)分離出來,放到獨立的面板里面,從而避免頻繁重建,也就動靜分離。 2.減少UI層疊關(guān)系,將同一個材質(zhì)的圖層放到同一層,或者同一個圖集能大量降低Drawcall 3.善于利用工具調(diào)試查看Drawcall
4.NGUI中,當用SetActive或alpha = 0的時候,NGUI的規(guī)則是從UIPanel中移除元素,這樣會引發(fā)FillAllDrawCalls重建整個網(wǎng)格,通過設(shè)置scale = 0 或 alpha 接近0來隱藏(因為這樣網(wǎng)格還在,DrawCall也在,不會打亂)的話,則只會重建單個網(wǎng)格,在優(yōu)化復(fù)雜面板時尤為有效。 5.NGUI中,在UIPanel上如果勾選了Static選項,意思是把該面板變?yōu)殪o態(tài)面板,所有的子對象都無法縮放、旋轉(zhuǎn)、移動(可以更改這些數(shù)值,但是不會有效果)。勾選了這個選項,可以減少輪詢的開銷。 總結(jié)NGUI優(yōu)勢: 1.開放源碼,NGUI的源碼是開放的。使得開發(fā)者可以隨意的查看代碼并修改,可以隨意修改其易用性或優(yōu)化性能。 2.配套工具鏈和積累的組件。NGUI的先發(fā)優(yōu)勢使得開發(fā)者積累了大量的開發(fā)組件和工具,經(jīng)過項目的驗證,已經(jīng)融入了開發(fā)的工作流中。 UGUI優(yōu)勢: 1.性能優(yōu)勢,作為Unity的親兒子,網(wǎng)格計算是C++下實現(xiàn)的、而且還可以放在子線程完成,性能天花板比NGUI高出了不少。 2.持續(xù)的更新和官方的支持。作為官方UI,支持和后續(xù)的優(yōu)化,肯定是會持續(xù)進行的。 在UGUI剛出來不久時,大部分團隊都還是在使用NGUI,因為積累的工作流都比較成熟,是久經(jīng)考驗的。而近兩年,使用UGUI的團隊變得原來越多,一是UGUI的工具鏈也越來越成熟好用了,二是因為UGUI的天花板確實要比NGUI要高。慢慢的使用UGUI的團隊也就越來越多了。 |
|
|