????????用過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代碼焚廊,
這里要說一下UIPanel在這其中的作用冶匹,可以看到UIWidget的depth改變以后,之間調(diào)用了UIPanel的RemoveWidget跟AddWidget方法咆瘟,重新將這個(gè)UIWidget進(jìn)行一次刪插操作嚼隘。而這個(gè)刪除跟插入操作不是一般的刪除跟插入,還順帶做了一大堆的事情袒餐。
首先我們看看刪除都做了什么飞蛹,
看上去好像只是在如果這個(gè)wiget的pepth為drawcall的開始或者結(jié)束值相等的時(shí)候,將mRebuild賦值為true灸眼∥蚤埽看起來好像沒有做什么對(duì)不對(duì),但是我們?cè)倏催@個(gè)mRebuild做了什么焰宣。
咋一看霉囚,好像也沒做什么呀,只是調(diào)用了一個(gè)叫UIPanel中的FillAllDrawCall的方法而已宛徊。且看
需要注意的是佛嬉,F(xiàn)illAllDrawCall是在UIPanel的LateUpdate中調(diào)用的,LateUpdate遍歷了所有的UIPanel闸天,當(dāng)每個(gè)panel的mRebuild為ture時(shí)暖呕,這個(gè)penel就調(diào)用自身的FillAllDrawCall方法。由于無法截圖更長苞氮,忽略了上面的一些代碼湾揽,只截了這段創(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上面了晒他,別急谆沃,且跟我慢慢分析。
這兩段代碼緊跟著我們上面的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)系又是如何確定的呢嗜诀。且看
前面說到了最后調(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è)方法隘世,
可以看到可柿,有個(gè)UpdateDrawCalls的方法根據(jù)UIPanel的設(shè)置不同而被調(diào)用。而正式這個(gè)方法以舒,遍歷了每個(gè)UIDrawCall并對(duì)其SortingLayer跟SortingOrder進(jìn)行了賦值操作
這里對(duì)每個(gè)UIDrawCall的RenderQueue趾痘,SortingLayer,SortgingOrder進(jìn)行了賦值
需要注意的是蔓钟,這里的SotringLayer屬性永票,如果useSortingOrder為false的話,他是被設(shè)置為null的
看引用可知滥沫,它就是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)大量內(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ì)看到
這是當(dāng)前Panel中所有的DrawCall毅待,可以看到我們場景中總共有兩個(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.reibang.com/p/7a033810706f? ??<論RenderQueue狂秦、SortingLayer、SortingOrder關(guān)系>