關(guān)于NGUI的depth的深度解析<一>

????????用過NGU的兄弟知道,NGUI是以一個(gè)depth的參數(shù)控制各個(gè)Rect的前后關(guān)系的。包括UISprite跟UILabel這些繼承是UIWidget的組件,當(dāng)然也包括UIWidget本身,UIPanel也有depth,但是UIPanel的depth跟UIWidget的是一樣的嗎?UIPanel是調(diào)整整個(gè)Panel與Panel之間的層級(jí)關(guān)系。而UIRect的depth是調(diào)整UIWidget之間的層級(jí)關(guān)系,雖然聽起來差不多,但是感覺有點(diǎn)小區(qū)別呢。本篇暫定只解析UIWidget的depth。 那么UIRect的depth是如何影響UI的先后層級(jí)關(guān)系的呢?

? ? ? ? 首先我們看UIRect的depth代碼,

depth—set

這里要說一下UIPanel在這其中的作用,可以看到UIWidget的depth改變以后,之間調(diào)用了UIPanel的RemoveWidget跟AddWidget方法,重新將這個(gè)UIWidget進(jìn)行一次刪插操作。而這個(gè)刪除跟插入操作不是一般的刪除跟插入,還順帶做了一大堆的事情。

首先我們看看刪除都做了什么,

RemoveWidget

看上去好像只是在如果這個(gè)wiget的pepth為drawcall的開始或者結(jié)束值相等的時(shí)候,將mRebuild賦值為true??雌饋砗孟駴]有做什么對(duì)不對(duì),但是我們?cè)倏催@個(gè)mRebuild做了什么。

lateupdate

咋一看,好像也沒做什么呀,只是調(diào)用了一個(gè)叫UIPanel中的FillAllDrawCall的方法而已。且看

FillAllDrawCall

需要注意的是,F(xiàn)illAllDrawCall是在UIPanel的LateUpdate中調(diào)用的,LateUpdate遍歷了所有的UIPanel,當(dāng)每個(gè)panel的mRebuild為ture時(shí),這個(gè)penel就調(diào)用自身的FillAllDrawCall方法。由于無法截圖更長(zhǎng),忽略了上面的一些代碼,只截了這段創(chuàng)建DrawCall的代碼。那么,這FillAllDrawCall里面做了什么,那 這個(gè)DrawCall到底是個(gè)什么東西呢,我們根據(jù)上面的這個(gè)截圖可以看出來,每個(gè)UIWidget都保存了一個(gè)自身引用的UIDrawCall,當(dāng)下一個(gè)UIWidget的所屬的材質(zhì)、貼圖、Shader有一者不一樣,則重新創(chuàng)建一個(gè)drawcall,否則刷新這個(gè)drawcall的開始depth跟結(jié)尾的depth。這個(gè)刷新方式,導(dǎo)致我們?cè)趧?chuàng)建UI界面的使用,也需要有些注意事項(xiàng),這個(gè)后面再說。

而depth的作用就在這里了,由此可見,UIRect的層級(jí)關(guān)系是跟UIDrawCall這個(gè)東西有關(guān)的。那么UIDrawCall又是個(gè)什么玩意呢?我們不是在研究depth嘛,怎么牽扯到UIDrawCall上面了,別急,且跟我慢慢分析。


FillAllDrwaCall
FillAllDrawCall

這兩段代碼緊跟著我們上面的DrawCall.Create()的地方,大概就是前后關(guān)系,在UIWidget的WriteBuBuffers中會(huì)將Wigiget的頂點(diǎn)(verts),UV,顏色等從UIGeonetry中寫入到所屬的drawCall中去,然后再DrawCall中的UpdateGeometry中進(jìn)行修改刷新渲染。也就是說,最終的我的UI的效果跟層級(jí)表現(xiàn)是根據(jù)DrawCall的渲染表現(xiàn)來呈現(xiàn)的,那drawcall之間的層級(jí)關(guān)系又是如何確定的呢。且看

RebuildMaterial

前面說到了最后調(diào)用了UIDrawCall的UpGeometry,在這個(gè)方法里面我們可以發(fā)現(xiàn),它在賦值了drawcall的Mesh的頂點(diǎn)跟UV一系列的賦值操作以后,將mesh賦值給了自己的MeshFiter(沒錯(cuò),就是用MeshFilter),然后調(diào)用了上圖的這個(gè)ReBuildMaterial方法,將drawCall的sortingLayer跟sotringOrder賦值給了render。由此真相大白,原來UISprite的背后是用DrawCall渲染的,而DrawCall是用mesh渲染的,層級(jí)的最終還是走的Unigy的Sortinglayer跟SortingOrder。

那么UIDrawCall的sortingLayer跟SortingOrder又是在哪里賦值的呢,我們之前說了,F(xiàn)illAllDrawCall是在Panel的LateUpdate方法中的。追根朔源我們可以發(fā)現(xiàn),在LateUpdate中還有一個(gè)方法,

LateUpdate

可以看到,有個(gè)UpdateDrawCalls的方法根據(jù)UIPanel的設(shè)置不同而被調(diào)用。而正式這個(gè)方法,遍歷了每個(gè)UIDrawCall并對(duì)其SortingLayer跟SortingOrder進(jìn)行了賦值操作

UpdateDrawCalls

這里對(duì)每個(gè)UIDrawCall的RenderQueue,SortingLayer,SortgingOrder進(jìn)行了賦值

需要注意的是,這里的SotringLayer屬性,如果useSortingOrder為false的話,他是被設(shè)置為null的

UsedSortingOrder

看引用可知,它就是UIPanel的Inspector面板上面的SotringOrder的toggle,如果被勾選,則上面的SortingLayer生效,否則,無論你將SortingLayer改成什么,它都是會(huì)設(shè)置為Null,而設(shè)置為null的話,系統(tǒng)會(huì)自動(dòng)設(shè)置為第一層的SortingLayer,默認(rèn)是Default,但是也不一定,如果你在Default前面又新建了其他比如Base層,那么它就會(huì)默認(rèn)設(shè)置成Base層,因?yàn)楝F(xiàn)在Base層已經(jīng)是第一層了。

文章開始時(shí)我們也說過,關(guān)于UIDrawCall機(jī)制導(dǎo)致我們創(chuàng)建UI的時(shí)候需要注意一些事情?;仡^看UIDrwaCall的地方,我們可以發(fā)現(xiàn)由于遍歷UIWiget的list進(jìn)行創(chuàng)建drawcall,一旦上一個(gè)的材質(zhì),shader或者貼圖有一者不同,那么它就會(huì)重新創(chuàng)建一個(gè)新的drawcall來保存當(dāng)前widget的渲染內(nèi)容,這樣一來,如果我們創(chuàng)建UI的時(shí)候,一不注意,就會(huì)導(dǎo)致drawcall數(shù)量激增。激增會(huì)有什么后果呢,最直觀的反應(yīng)就在性能上,很可能導(dǎo)致我們的游戲卡頓,浪費(fèi)大量?jī)?nèi)存在渲染UI上面。

那么如何避免呢,我們可以盡量保持同一個(gè)圖集的Sprite在順序的depth上面,這樣就會(huì)將他們都放在同一個(gè)DrawCall中進(jìn)行渲染。當(dāng)然,也沒有必要斤斤計(jì)較,因?yàn)榇罱║I真的很累,手都能點(diǎn)到抽搐~_~。

搭建UI的時(shí)候,可以考慮depth分層機(jī)制,比如[0,20]是屬于背景的,比如[21,40]是屬于文字的,文字的depth盡量跟Sprite分開,因?yàn)槲覀兺ǔV皇褂靡粌蓚€(gè)文字,而且文字都在Sprite前面,能放一起當(dāng)然最好不過。當(dāng)然只是個(gè)參考,不建議加一個(gè)UI就加一層depth,這樣要插入一個(gè)就很麻煩,層級(jí)很容易錯(cuò)亂。

可以看到我們的Panel下面有個(gè)Show Draw Call的按鈕,點(diǎn)擊就會(huì)看到

DrawCallTool

這是當(dāng)前Panel中所有的DrawCall,可以看到我們場(chǎng)景中總共有兩個(gè)DrawCall,這個(gè)panel占了一個(gè)。很清晰易懂,材質(zhì),以及包含哪些Widgets,RederQueue跟三角面數(shù)都貼出來了。Widgets可以看到我們這個(gè)DrawCall中包含了多少Widget元素,也就是包含多少UISprite跟UIlabel這些繼承子UIWidget的組件,而drawCall的個(gè)數(shù)很很清晰,我們創(chuàng)建的時(shí)候,可以根據(jù)這個(gè)面板進(jìn)行調(diào)整優(yōu)化。

另外如果對(duì)Unity的SortingLayer,RenderQueue跟SortingOrder不熟的同學(xué),可以查看我的上一篇文章哦!

地址:http://www.itdecent.cn/p/7a033810706f? ??<論RenderQueue、SortingLayer、SortingOrder關(guān)系>

最后編輯于
?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

  • 目錄 1、介紹兩大UI插件NGUI和UGUI2、unity渲染順序控制方式3、NGUI的控制4、UGUI的控制5、...
    小飛不會(huì)飛_閱讀 7,342評(píng)論 4 13
  • 轉(zhuǎn)自:https://blog.csdn.net/dingxiaowei2013/article/details/...
    豆錚閱讀 1,379評(píng)論 0 2
  • 以下內(nèi)容基于 NGUI v.3.11.2 。示例是在 Unity 5.5 中測(cè)試。 渲染結(jié)構(gòu) NGUI 用 Pan...
    YLME閱讀 1,957評(píng)論 0 1
  • 一:什么是協(xié)同程序?答:在主線程運(yùn)行時(shí)同時(shí)開啟另一段邏輯處理,來協(xié)助當(dāng)前程序的執(zhí)行。換句話說,開啟協(xié)程就是開啟一個(gè)...
    CrixalisAs閱讀 2,234評(píng)論 1 7
  • 一:什么是協(xié)同程序? 答:在主線程運(yùn)行時(shí)同時(shí)開啟另一段邏輯處理,來協(xié)助當(dāng)前程序的執(zhí)行。換句話說,開啟協(xié)程就是開啟一...
    好怕怕閱讀 4,030評(píng)論 2 23

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