Unity 2017 Game Optimization 讀書筆記 Dynamic Graphics (4)

Optimizing Unity UI

本章講探討一些能夠提升UGUI性能的優化方法。

1.Use more Canvases

一個Canvas的主要任務就是管理它層級下的所有UI元素,並且通過Draw Call去渲染它們。其中Canvas一個重要的事兒就是對這些元素進行合批來減少draw call。但是如果對Canvas或者其下邊的child元素進行了修改,就會dirty這個Canvas,導致Canvas的重製。Canvas的重製開銷很大,很容易引起性能的問題。Unity中很多東西都會導致Canvas的重製,如果當一些操作發生時我們發現UI導致了CPU極大的開銷,就應該考慮用更多的Canvases。

一個常見的誤區就是使用一個Canvas來製作UI。

如果只有一個Canvas,當UI中有任何變化時,它必須check每一個元素,隨之Canvas越來越複雜,Check的開銷也會越來越大。如果使用多個Canvas,就可以當某個元素髮生變化時,隻影響其所在Canvas,會影響較少的元素進行重建,從而減少性能開銷。

多個Canvas的缺點是各Canvas之間不能合批,因此應該是儘量保證相似的使用相同material的元素在同一個Canvas下。

2.Separate objects between static and dynamic canvases

可以根據更新的時機和頻率把UI元素分成三組:

Static (靜態):一直不會改變的UI元素,比如背景圖等

Incidental Dynamic(動態):可以改變,但是隻是在需要的時候會改變,比如Button的press和hover響應

Continuous Dynamic(持續動態):持續動態改變,例如動畫元素

根據這個分組,可以把UI元素放入三個不同的Canvas中,這樣可以降低Canvas重建的開銷。

3.Disable Raycast Target for noninteractive elements

擁有Raycast Target的UI元素可以對Click,Taps等用戶操作產生響應。GraphicsRaycaster會循環遍歷去check哪個Raycast Target是響應目標,關掉UI上並不需要的Raycast Target可以避免GraphicsRaycaster無意義的check,從而減少開銷。

4.Hide UI elements by disabling the parent Canvas Component

可以通過設置UI元素的所屬Canvas是否enable來達到隱藏該Canvas下所有UI元素的目的,優點是可以避免Canvas重建,缺點是如果腳本中有Update(), FixedUpdate(), LateUpdate()或其他持續性的代碼,會依然被調用,因爲這只是使得Canvas不被渲染而已。

5.Avoid Animator Components

應該完全避免在UI中使用Animator,Animator會在每一幀中該UI元素的屬性從而導致大量UI信息的重新生成。應該通過自己寫tweening腳本或者一些插件來完成這些操作。

6.Explicitly define the Event Camera for World Space Canvases

在2D和3D中Canvas中的UI元素都可以用來產生交互響應,這取決於這個Canvas的Render Moder設置爲Screen Space (2D) 還是World Space (3D)。每當有響應時,Canvas會通過其event Camera屬性來確定使用哪個攝像機。2D Canvas默認設置爲Main Camera,但是3D默認設置爲null。這會帶來不必要的開銷,因爲即使設置爲null,每次使用時也是使用Main Camera,但是會調用FindObjectWithTag()函數。這個函數雖然沒有Find()函數開銷大,但是也是不能忽視的。所以如果使用3D模式,要手動設置好合適的event Camera。

7.Don't use alpha to hide UI elements

把UI元素中Colour屬性的alpha設爲0依然會產生Draw Call,應該通過IsActive來控制其是否隱藏,另一種方法是使用Canvas Group,使用Canvas Group可以控制所有Child的alpha值,通過Canvas Group設置alpha爲0後,渲染時會剔除掉所有child 元素,因此不會有Draw Call的開銷。

8.Optimizing ScrollRects

ScrollRect是移動遊戲中常用的組件,但是ScrollRect的性能會根據其大小有非常大的開銷,因爲它需要不斷的進行佈局重建。接下來會介紹幾條關於ScrollRect的優化。

8.1 Make sure to use a RectMask2D

使用scrolling UI最簡單的一種方式可能就是將所需要展示的UI內容的Depth設置爲低於ScrollRect,單這是一種非常不好的實現方式,因爲整個Scroll Rect都會參與重建,沒有culling的過程。

使用RectMask2D腳本可以對超出bound的的部分進行剪裁,它的消耗在於要計算哪些object需要剪裁掉,但是要比把所有內容都渲染出來強多了。

8.2 Disable Pixel Perfect for ScrollRects

Pixel Perfect是Canvas中的一個設置,會強制要求UI元素在屏幕中要像素精準。對於持續動畫和移動的物體,這個設置有些沒必要,關掉這個設置可以節省ScrollRect的一些開銷,但是要注意的是這個設置是對整個Canvas的設置,會對Canvas下的所有UI元素產生影響,要確定其他元素可以接受不是Pixel Perfect。

8.3 Manually stop ScrollRect motion

當ScrollRect即使移動的速度非常慢,每幀幾個像素時,也依然會重製。因此我們可以通過ScrollRect.velocity獲取速度值,判斷其在低於某個速度範圍下時,就調用 ScrollRect.StopMovement()停止移動,從而避免無謂的重建。

9.Use empty UIText elements for full-screen interaction

我們經常使用一個大UIImag,將其設置爲透明覆蓋在屏幕上,來作爲透明遮罩強制用戶點擊最上層的彈框。但是這種操作有可能會打破batching,更好的方式是使用一個不帶字體和文字的UIText,這樣就不會有任何東西需要渲染,但在bounding-box範圍內依然可以交互響應。

10.Check the Unity UI source code && Check the documentation

可以查看UnityUI的源代碼:https://bitbucket.org/Unity-Technologies/ui.

如果我們對UI中一些問題不滿意,我們可以自己手動修改UI源代碼,重新編譯後導入工程中。

上邊只是列出了一些在文檔中很少見或者非常重要的一些優化方法,關於UI還有很多其他優化點,本書也沒辦法都囊括進來,可以查看文檔:

https://unity3d.com/learn/tutorials/temas/best-practices/guide-optimizing-unity-ui

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章