UGUI效能優化之Canvas

2021-10-07 10:38:49 字數 2171 閱讀 2668

前言,覺得好的同學別忘了給個好評哦,另外,如果有什麼疑問的,歡迎隨時提問~~

自從unity問世以來,ui一直都存在比較大的問題,自帶的ongui不能所見即所得,製作過程比較麻煩。於是出現了很多第三方的優秀的ui外掛程式,比如很多專案裡面用到的ngui,或者後來出的fairygui。unity官方在4.x時代開始推出了自己的新ui系統,名為ugui。由於是官方出品,所以選擇使用的人也比較多。

ugui是乙個比較完整的所見即所得式的ui系統, 不過說實在的,我個人感覺它的成熟度還是差了點,有很多需要注意的地方,不然就會產生很多效能上的問題,比如drawcall問題和執行時的效率問題。我就曾經在專案中遇到了,ugui用的不好,它產生的消耗比3d場景內的地圖和角色消耗還高的情況。這裡分享一點經驗,主要講一下ui重繪的消耗和圖集的一些問題。

要了解ugui的一些坑,首先要明白它是基於什麼原理來運作的。

首先,ugui還是基於網格模型渲染的。乙個矩形,實際上還是由4個頂點組成的乙個mesh顯示出來的,和正常的mesh模型渲染一樣,它使用了材質球和貼圖。我們平常看不到這些元素,是因為渲染ui用的mesh網格是在執行中才生成的,它預設使用了untiy內建的乙個預設的材質球,然後使用我們指定的ui作為貼圖。

開啟乙個image來看看,可以看出material是空的,那是因為它有預設的材質球。然後unity也允許你再指定乙個material來渲染。值得注意的是,這個材質球如果你是直接掛在ui的image上面,那麼如果你在執行時修改material,將會改到的是share的原始material。所以最好的做法是在**裡面生成乙個材質球的複製例項,然後再賦給image使用。

明白了單個ui元件的渲染原理之後,接下來需要說說渲染合併的問題。既然乙個image就是乙個mesh,然後上面有單獨的貼圖顯示。那麼是不是就代表著,我乙個介面裡有有100個ui元件,那麼就會產生100個mesh,產生100個drawcall呢?

從原理上的確是會這樣,但實際執行的時候,並沒有產生這樣的結果。這裡unity引入了乙個canvas(畫布)的概念。在預設建立的ugui根節點上面,你可以看到這個canvas

它定義了一些東西,比如當前畫布的渲染模式、排序情況。

然後當你往這個canvas裡面新增其他ui元件的時候,這些元件實際上就是被這個canvas統和在一起了。比如,同乙個canvas裡面有100個image,canvas將會把100個單獨的mesh合併成乙個大的sharemesh,用於渲染。如果剛好這100個image都是使用了相同的或者是同乙個圖集裡面的,那麼由於使用的mesh只有乙個(sharemesh),材質球都是同乙個(內建的預設材質球),貼圖也是同一張,所以得到的結果就是,drawcall只有乙個。

這實際上就是ugui最基本的優化思路了。合併sharemesh、合併圖集,減少drawcall。但在實際專案的操作中,會遇到很多問題。

就拿sharemesh來說,我們可以把場景的靜態合併拿來對比一下。這個sharemesh和場景合併成combinedmesh是一樣的,把很多小模型合成乙個大模型。但可以想象,場景的模型合併是靜態的,也就是說它是擺在那裡不會動的。大部分情況下,ui也是不會動的,在這種情況下,合併sharemesh沒有太大的問題。但還是會有很多會動的時候。比如說,arpg很喜歡在角色頭頂上顯示角色名字,名字會跟隨著角色移動。再比如,聊天裡面不停的刷各種文字聊天資訊,或者你需要乙個圖示從左邊飛到右邊的動畫,或者你的血量條需要動態變化長度之類,等等。這些情況下,由於單個顯示元素的mesh 形狀發生變化(文字的改變實際上也是改變了mesh形狀),如果原來這些ui元素就是和其他所有ui元素合併同乙個sharemesh的,那麼問題就來了,假如你ui元素非常多,產生了乙個2m的sharemesh(這是乙個比較極端的例子,實際上一般的sharemesh都是幾百k,出現這麼大的sharemesh本身就需要注意了),由於乙個小頂點發生了改變,導致2m的整體sharemesh也需要重新的生成頂點資訊,並且整個sharemesh重新渲染,這明顯是得不償失的。你會發現在ui動畫的過程中,整個遊戲都在卡。卡的是cpu方面的實時合併網格頂點,和渲染那邊的整個大mesh重新繪製。

那麼怎麼解決這個問題呢?思路也像場景模型和角色模型的關係一樣。首先要知道的是,在根節點下面掛了canvas之後,還是可以在子節點上面繼續的掛canvas的。這樣,從理論上說,unity會找到最小單位的canvas作合併。既然大部分的ui是不會動的,那麼我們可以做一些分層,把不會動的元素放在同一層,然後會動的元素,根據動的頻率和型別,分別在他們的子節點上面掛上canvas。這樣就可以在保證大部分ui元素能合併渲染的基礎上,減少整體重繪的範圍、這就是所謂的動靜分離。

UGUI官方文件canvas

canvas canvas 是放置ui 元素的區域。canvas 是乙個帶有 canvas 元件的遊戲物體,並且所有的 ui元素必須是 canvas 的子物體。當你建立乙個新的 ui元素時,比如通過 gameobject 選單 ui image 建立乙個 image 此時,如果場景中沒有 canva...

canvas動畫實戰與效能優化

插播一篇關於canvas動畫及效能優化的文章,為我們可以更好的進入到webgl的世界奠定基礎。首先介紹一下我們要實現的動畫內容 夜空中的流星原始碼。今天就來跟大家詳細分享一下如何進行編寫canvas動畫以及如何進行優化。canvas的頁面組成是非常簡單的。如下所示 您的瀏覽器不支援canvas標籤,...

canvas效能優化 離屏渲染

為了使使用者達到更好的體驗,做動畫的時候都知道用requestanimationframe了,但是他也是有極限的,當繪製的東西足夠多或者複雜的時候,頻繁的刪除與重繪降低了很多效能。在canvas中粒子系統應該算是比較常見的一種了,現在建立乙個canvas畫布,並繪製100個粒子在整個畫布上由上至下做...