原文鏈接:https://unity3d.com/cn/learn/tutorials/topics/best-practices/other-ui-optimization-techniques-and-tips
其他UI優(yōu)化技術(shù)和提示
很多時候并沒有一個簡潔的方法來優(yōu)化UI丧荐。本章節(jié)包含了一些可能會提高UI性能的建議籍嘹,但是一些是在結(jié)構(gòu)上不簡潔的,或是難于維護(hù)鸟款,或是有一些不好的邊際效應(yīng)臂容。其他的是一些使UI初始開發(fā)變成簡單的行為的解決方案哩治,但是也會更容易造成一些性能問題猿规。
基于RectTransform的布局
Layout組件性能消耗相對昂貴,因為它們必須在其每次標(biāo)記dirty時重新計算其子元素的大小和位置(有關(guān)詳細(xì)信息尤揣,請參閱Fundamentals章節(jié)的Graphic rebuild部分)搔啊。如果給定Layout中的元素數(shù)量相對較少且數(shù)量固定,并且Layout結(jié)構(gòu)相對簡單北戏,則可以使用基于RectTransform的Layout替換Layout负芋。
通過分配一個RectTransform的錨點,RectTransform的位置和大小就能基于其父級進(jìn)行縮放嗜愈。例如旧蛾,兩個RectTransform就能實現(xiàn)一個簡單的兩列的布局:
左列的錨點應(yīng)該是X:(0,0.5)和Y:(0,1)(覆蓋左邊屏幕)
右列的錨點應(yīng)該是X:(0.5,1)和Y:(0,1)(覆蓋右邊屏幕)
RectTransform的大小和位置的計算將由Transform系統(tǒng)本身在本機(jī)代碼中驅(qū)動。這通常比依靠Layout系統(tǒng)更高效蠕嫁。編寫基于RectTransform的布局的MonoBehaviour腳本也是可以的锨天。但是,這是一項相對復(fù)雜的工作剃毒,也超出了本指南的范圍病袄。
禁用Canvas Renderer
當(dāng)顯示或隱藏一個UI分立的部分時,通常會啟用或者禁用這個UI的根游戲物體赘阀。這確保了在這個禁用的UI中沒有組件接收輸入或是執(zhí)行Unity的回調(diào)函數(shù)益缠。
然而,這也會導(dǎo)致Canvas拋棄其VBO(頂點緩沖對象)數(shù)據(jù)基公。重新啟用Canvas會使Canvas(包括所有的子Canvas)強(qiáng)制進(jìn)行rebuild和rebatch進(jìn)程幅慌。如果這種情況發(fā)生的非常頻繁,增加的CPU使用會造成應(yīng)用程序的幀率卡頓轰豆。
一種可能的方法是將UI的顯示和隱藏控制在其Canvas和子Canvas中胰伍,僅僅是啟用或者禁用關(guān)聯(lián)到Canvas或是子Canvas的Canvas Renderer組件(并不是指真的Canvas Renderer組件齿诞,而是指依賴Canvas Renderer組件的image,text等組件)骂租。
這將UI的網(wǎng)格就不會被繪制掌挚,它們將會保持駐留在內(nèi)存中,它們的原始batch將會被保存菩咨。此外,在UI的層級中將不會有OnEnable或是OnDisable回調(diào)函數(shù)執(zhí)行陡厘。
但請注意抽米,這樣的方法將不會消除GraphicRegistry中UI的圖形,所以它們?nèi)匀粫霈F(xiàn)在Graphic Raycast要檢查的組件列表中糙置。這種方法不會禁用任何隱藏UI中的MonoBehaviour腳本云茸,所以這些MonoBehaviour腳本將會接收Unity的生命周期回調(diào),比如說Update谤饭。
為了避免這個問題标捺,將以這種方式禁用的UI上的MonoBehaviour腳本不應(yīng)該直接來實現(xiàn)Unity的生命周期回調(diào)函數(shù),而是應(yīng)該通過掛載到UI根游戲物體上的“Callback Manager” MonoBehaviour腳本來接收回調(diào)函數(shù)揉抵。每當(dāng)UI被顯示和隱藏的時候亡容,就會通知Callback Manager,這會確保生命周期事件根據(jù)需要傳播或是不傳播冤今。關(guān)于Callback Manager模式的進(jìn)一步解釋超越了本指南的范圍闺兢。
分配事件攝像機(jī)
如果使用Unity的內(nèi)置Input Manager并且Canvas的渲染模式設(shè)置為World Space或是Screen Space – Camera模式,始終分別的設(shè)置事件攝像機(jī)和渲染攝像機(jī)非常重要戏罢。在腳本中屋谭,它始終作為worldCamera屬性公開。
如果這個屬性沒有設(shè)置龟糕,那么UGUI將會在掛有攝像機(jī)的游戲物體中通過主攝像機(jī)標(biāo)簽來尋找主攝像機(jī)桐磁,至少每個World Space或是Camera Space的Canvas都會發(fā)生這種查找。GameObject.FindWithTag眾所周知非常慢讲岁,所以強(qiáng)烈建議所有的World Space和Camera Space的Canvas都在設(shè)計時或初始化時設(shè)置其Camera屬性我擂。
這個問題不會發(fā)生在Overlay的Canvas上。