1. 程式人生 > >UGUI的一些效能優化經驗

UGUI的一些效能優化經驗

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

阿趙我也是基於信任官方出品的心理,在最近的兩個專案裡面都使用UGUI進行開發。UGUI是一個比較完整的所見即所得式的UI系統, 不過說實在的,我個人感覺它的成熟度還是差了點,有很多需要注意的地方,不然就會產生很多效能上的問題,比如DrawCall問題和執行時的效率問題。我就曾經在專案中遇到了,UGUI用的不好,它產生的消耗比3D場景內的地圖和角色消耗還高的情況。老實說,我用UGUI也用的不好,這裡也只是分享一點經驗,這次主要講一下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元素能合併渲染的基礎上,減少整體重繪的範圍。

聽完上面的一些關於Canvas的說法之後,你是不是有種想法,那麼那些會動的東西要不掛多幾層Canvas,讓它控制得更細膩?當初我也是這樣想的。不過後來發現這樣做很有問題。Canvas存在一個重繪的問題。如果你把一個Canvas的節點SetActive為false之後,再在它身上做改變座標之類的操作,再把Canvas節點SetActive為true,這時候Canvas渲染的還是之前的畫面,並沒有把改變的東西渲染到。在這個時候,要麼Canvas裡面的元素稍微變化,讓它被動的觸發重繪,要麼呼叫ForceUpdate的API讓Canvas主動重繪。但這樣的操作如果在Canvas嵌套了很多層之後,是很難去控制的,也不可能每次都強制主動重繪Canvas,畢竟很多時候是沒必要這樣做的。最重要的一點是,編寫UI框架的時候,不應該要以後寫業務邏輯的人去關心業務上導致UI顯示發生改變後,再去做些什麼樣的潛規則才能正常顯示出來。所以我建議Canvas也不要分得太多,特別不要巢狀得太多層次,導致失去控制了。

說完Canvas的ShareMesh合併網格,最後再說一下圖集的問題。如果遊戲內容比較多,是不太可能把所有的UI圖片都合併在同一個圖集裡面的。所以必然會產生多個圖集的問題。而使用同一個圖集的Image能合併成一個DrawCall的前提,是他們中間沒有再穿插著使用了其他圖集的Image。這裡指的穿插,也包括矩形邊緣的穿插。所以你可能看到兩張圖好像沒有疊在一起,但也有可能因為透明區域的原因產生了疊加。
這裡寫圖片描述

這裡寫圖片描述
所以在設計UI的時候,最好避免太多層疊在一起的設計。邊界也儘量的分明。

這樣是一個理想中的設計方向,但實際上很多UI設計師在設計的時候覺得有這樣的限制是不好看的,他們喜歡做一些疊層作為修飾效果。所以也不能絕對的說不能做,只是在做疊層的時候,需要考慮清楚,每疊一層,疊的層是不是可以合併的,儘量多考慮一下疊完之後,圖片的元素需要怎樣分圖集才合理。然後如果是在介面邊框上面加花,我覺得這種情況是必須要分離出來疊層了。因為本身UI介面一般都是做成九宮拉伸的,不能因為你加了條很大的龍作為裝飾,就導致底框的背景圖也出的很大。

雖然很多剛入門Unity的人,特別是程式設計師,在進公司之後都會被安排為做UI功能。但我一直不認為UI就是一個這麼簡單的工作。要懂得一個UI系統的潛規則,做好效能優化,讓自己做出的介面比別人的好看又流暢,我一直都覺得是一個很困難的主題。

對於UI美術來說,如果不懂這些優化的原理,在設計UI結構的時候可能就會產生很多程式設計師也無法去解決的問題,最後只能要麼效能差,要麼大改方案重新做。我覺得懂得思考這些問題之後,才算是一個合格的遊戲UI設計師,而不僅僅是會使用Photoshop,畫出圖片效果。

相關推薦

UGUI一些效能優化經驗

自從Unity問世以來,UI一直都存在比較大的問題,自帶的OnGUI不能所見即所得,製作過程比較麻煩。於是出現了很多第三方的優秀的UI外掛,比如很多專案裡面用到的NGUI,或者後來出的FairyGUI。Unity官方在4.x時代開始推出了自己的新UI系統,名為U

WPF效能優化經驗總結

原文地址:https://www.cnblogs.com/chiniao/archive/2010/08/09/1795499.html WPF效能優化一、Rendering Tier 1. 根據硬體配置的不同,WPF採用不同的Rendering Tier做渲染。下列情況請特別注意,因為在這

淺談Vue 專案效能優化 經驗

我優化公司的專案總結的幾點: 1、先檢視引入的圖片大小,如果太大了,可以壓縮,壓縮路徑:https://zhitu.isux.us/ 2、程式碼包優化, 待下專案開發完成。進行打包原始碼上線環節,需要對專案開發環節的開發提示資訊以及錯誤資訊進行遮蔽,一方面可以減少上線程式碼包的大小;另一方面

關於SQL SERVER資料庫的效能優化經驗

那怎麼才算是規範化的設計流程:規範化設計的過程就是按不同的正規化,將一個二維表不斷地分解成多個二維表並建立表之間的關聯,最終達到一個表只描述一個實體或者實體間的一種聯絡的目標。目前遵循的主要正規化包括1 NF、 2 NF、3 NF、BCNF、4NF和 5NF等幾種;在工程中3NF、BCNF應用得最廣泛,推薦

資料庫效能優化經驗總結

1.資料庫訪問優化法則 要正確的優化SQL,我們需要快速定位能性的瓶頸點,也就是說快速找到我們SQL主要的開銷在哪裡?而大多數情況效能最慢的裝置會是瓶頸點,如下載時網路速度可能會是瓶頸點,本地複製檔案時硬碟可能會是瓶頸點,為什麼這些一般的工作我們能快速確認瓶頸點呢,因為

火星時代老師總結使用Unity 3D優化遊戲執行效能經驗

      流暢的遊戲玩法來自流暢的幀率,而我們即將推出的動作平臺遊戲《Shadow Blade》已經將在標準iPhone和iPad裝置上實現每秒60幀視為一個重要目標。   以下是我們在緊湊的優化過程中提升遊戲執行效能,並實現目標幀率時需要考慮的事項。   當基本遊戲功能到

Java基礎學習總結(135)——Java程式碼效能優化實踐經驗再總結

前言 程式碼優化的最重要的作用應該是:避免未知的錯誤。在程式碼上線執行的過程中,往往會出現很多我們意想不到的錯誤,因為線上環境和開發環境是非常不同的,錯誤定位到最後往往是一個非常小的原因。然而為了解決這個錯誤,我們需要先自驗證、再打包出待替換的class檔案、暫停業務並重啟,對於一個成熟的專

web前端效能優化一些方法

web前端是應用伺服器處理之前的部分,前端主要包括:HTML,CSS,javascript,image等各種資源,針對不同的資源有不同的優化方式。  (2)減少DNS查詢: 內容優化 (1)減少HTTP請求數:這條策略是最重要最有效的,因為一個完整的請求要經過DNS定址,

Hbase常用優化、Hbae效能優化、Hbase優化經驗總結

Hbase優化 1.預先分割槽 預設情況下,在建立 HBase 表的時候會自動建立一個 Region 分割槽,當匯入資料的時候,所有的 HBase 客戶端都向這一個 Region 寫資料,直到這個 Region 足夠大了才進行切分。一種可以加快批量寫入速度的方法是通過預先建立一些空的 Reg

[轉載]雅虎團隊經驗:網站頁面效能優化的34條黃金守則

最近在看HTTP相關的內容,偶然看到一篇不錯的博文,現分享給大家。   雅虎團隊經驗:網站頁面效能優化的34條黃金守則1、儘量減少HTTP請求次數      終端使用者響應的時間中,有80%用於下載各項內容。這部分時間包括下載頁面中的影象、樣式表

MySQL效能優化的最佳20條經驗

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效能。這裡,我們不會講過多的SQL語句

SQL效能優化十條經驗,後臺程式設計師都需要掌握

1.查詢的模糊匹配儘量避免在一個複雜查詢裡面使用 LIKE '%parm1%'—— 紅色標識位置的百分號會導致相關列的索引無法使用,最好不要用.解決辦法:其實只需要對該指令碼略做改進,查詢速度便會提高近百倍。改進方法如下:a、修改前臺程式——把查詢條件的供應商名稱一欄由原來的文字輸入改為下拉列表,使用者模糊輸

MySQL效能優化的最佳21條經驗

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效能。

MySQL效能優化二十一條實戰經驗

現在,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的效能。這裡,我

Sql的一些優化經驗

Sql的一些優化經驗 Sql的一些優化經驗 1.like模糊匹配 2.索引欄位 3.where欄位 4.傳遞引數時

Java程式設計效能優化一些事兒

1. 儘量在合適的場合使用單例 使用單例可以減輕載入的負擔,縮短載入的時間,提高載入的效率,但並不是所有地方都適用於單例,簡單來說,單例主要適用於以下三個方面: 第一,控制資源的使用,通過執行緒同步來控制資源的併發訪問; 第二,控制例項的產生,以達到節約資源的目的;

mysql效能優化一些建議

mysql效能優化的一些建議 1、EXPLAIN 你的 SELECT 查詢 檢視rows列可以讓我們找到潛在的效能問題。 2、為關鍵欄位新增索引,比如:where, order by, group by等後面的欄位 注意:like '%abc%'; 是不會用到索引的 只有 like 'abc%' 才會用到

記錄這幾年做頁遊的一些客戶端優化經驗

1、UI載入做快取,快取指定的UI,可以減少常用的UI重複載入、建立 2、對UI進行封裝,方便使用和統一管理 3、限制客戶端同屏玩家的顯示數量 4、小怪死亡復活特別頻繁,一種方案是把訊息合併一起傳送,另一種方式是小怪死亡後,不是重新重新整理一個,是把死亡的小怪復活,這樣減少了大量的訊息量,客戶端也不需要

Java 程式碼效能優化總結(過來人經驗

Java 程式碼效能優化總結(過來人經驗) 程式設計師界的彭于晏 2018-10-10 18:11:54 代 碼優化,一個很重要的課題。可能有些人覺得沒用,一些細小的地方有什麼好修改的,改與不改對於程式碼的執行效率有什麼影響呢?這個問題我是這麼考慮的,就像 大海里面的鯨魚一樣,它吃

MySQL效能優化的21條最佳經驗

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於Web應用尤其明顯。關於資料庫的效能,這並不只是DBA才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對操作資料庫時(尤其是查表時的SQL語句),我們都需要注意資料操作的