Unity項目中UI同學(xué)需知的程序相關(guān)要點

背景和目的

本文的背景是《獨立防線》(Killer)項目已進(jìn)行到了一定階段。雖然之前定下了UI制作規(guī)范,但中途也更新了規(guī)范,但程序和美術(shù)沒有具體面對面溝通,也沒有闡述規(guī)范的原因和落地方法。
所以,本文目的是為UI美術(shù)同事介紹:1、手游性能相關(guān)的標(biāo)準(zhǔn)是什么;2、具體制作時需要注意什么;3、什么樣的UI流程是高效的。
注,以下內(nèi)容并非要求UI美術(shù)同學(xué)都掌握、或者要求UI美術(shù)單獨去處理。而是希望UI美術(shù)同學(xué)能知道有這些一回事需要考慮。最重要的是:在設(shè)計之初,能意識到可能有問題,需要找程序去溝通。

體驗和性能

極端的體驗和極端的性能都不現(xiàn)實。

極端的體驗

極端的性能(從2015年的標(biāo)準(zhǔn)來看)

在手游平臺上,我們應(yīng)該追求的是體驗和性能平衡。

體驗和性能的平衡

性能評估標(biāo)準(zhǔn)

游戲中,任一元素(UI圖片、特效、模型等)對性能的影響都可以拆分為以下4種影響。


影響性能的4大方面

現(xiàn)就UI相關(guān)的影響進(jìn)行舉例如下。

CPU消耗

CPU負(fù)責(zé)把UI界面的邏輯結(jié)構(gòu)進(jìn)行更新、匯總,并負(fù)責(zé)把這些數(shù)據(jù)準(zhǔn)備好。最后把這些信息傳給GPU。

UI一般影響CPU的因素包括:

  • 界面結(jié)構(gòu)復(fù)雜度
  • 界面結(jié)構(gòu)變化頻率
  • 動畫復(fù)雜度
復(fù)雜的界面結(jié)構(gòu)

GPU消耗

GPU負(fù)責(zé)最終畫面的繪制、渲染。因為渲染是復(fù)雜的流程、且運(yùn)算量巨大、且手機(jī)GPU固有的硬件限制(核心數(shù)少、浮點運(yùn)算速度慢),手游的性能瓶頸往往都發(fā)生在GPU。
也就是說,GPU消耗是性能優(yōu)化的重中之重
UI一般影響GPU的因素包括:

  • 繪制次數(shù)(drawcall),和單張圖片的數(shù)量等因素相關(guān)
  • 圖片最終在屏幕所展現(xiàn)的面積
  • 圖片是否透明
  • shader的復(fù)雜度
  • 重繪度(overrdraw,單位像素的重新繪制次數(shù))

其中,特別值得注意的是drawcall重繪復(fù)雜度

drawcall

每一個不同“材質(zhì)”的東西都需要占用一個drawcall。每多一個drawcall必然帶來額外的CPU消耗和GPU消耗。


UI界面的drawcall次數(shù)為125次

可以簡單認(rèn)為,當(dāng)兩個東西的材質(zhì)的shader相同,且紋理相同,則它們是同一個材質(zhì),在渲染它們的時候,引擎會進(jìn)行優(yōu)化,會合并drawcall為1個。

overdraw

overdraw健康的UI界面
overdraw不健康的UI界面

overdraw表示單位像素的重新繪制次數(shù)
右部表示overdraw的程度,越“亮”的區(qū)域表示overdraw的程度越高,也就越消耗GPU。

外存消耗

外存消耗指的是資源在用戶“硬盤里占用了多少多少M”。
如果外存過大,可能導(dǎo)致用戶不愿意下載,或者下載安裝后,硬盤空間不夠,安裝不成功。
一般影響外存的因素包括:

  • 圖片數(shù)目
  • 圖片的分辨率大小
  • 圖片是否壓縮

另外,優(yōu)化了外存,內(nèi)存往往也會從中受益。

內(nèi)存消耗

內(nèi)存消耗指的是“游戲在實際運(yùn)行時,占用多少M”。
如果內(nèi)存過大,可能會導(dǎo)致用戶游戲體驗不流暢,甚至crash。
一般影響內(nèi)存的因素包括:

  • 圖片數(shù)目
  • 圖片的分辨率大小
  • 圖片的分辨率是否是2的N次方,
  • 圖片是否壓縮

UI制作要點

UI輸出的圖片,可在Unity里設(shè)置為新的等比縮放分辨率

正因如此,UI美術(shù)同學(xué)在輸出UI貼圖時,一般情況下按美術(shù)示意圖的原分辨率輸出即可。


輸出圖原本的分辨率為788x488

輸出圖在Unity里被設(shè)置為寬高不超過512

單獨調(diào)分辨率的工作,目前是由開發(fā)同學(xué)進(jìn)行。最理想的工作流程,是UI美術(shù)同學(xué)在導(dǎo)圖到Unity的時候,就單獨按需設(shè)置分辨率(和特效場景模型同學(xué)的工作流程一樣)。
至于什么情況下需要進(jìn)行降分辨率操作,見下文。

低頻變化的圖片的分辨率可以很小

本方法能為GPU、外存、內(nèi)存帶來好處

低頻變化的圖片指的是純色的、漸變等變化比較平緩的圖片。
低頻變化的圖片拉伸后仍能表現(xiàn)非常類似的效果,這是因為GPU在圖片采樣時會進(jìn)行相鄰像素的插值,從而能大概還原之前的平滑度。
總而言之,低頻變化的圖片的分辨率可以很小。
實例如下。

低頻變化圖片:原圖512x512

低頻變化圖片:輸出給程序的圖片縮小為32x32

低頻變化圖片:程序在使用時將32x32拉伸為512x512

“好”的UI可以拉起“不好的”UI的表現(xiàn)

本方法能為GPU、外存、內(nèi)存帶來好處

“好”的UI可以拉起“不好的”UI的表現(xiàn)

“好”的UI可以拉起“不好的”UI的表現(xiàn)這句話可以有以下的理解:

  • 不壓縮的UI可以拉起壓縮的UI表現(xiàn)
  • 高分辨率的UI可以拉起低分辨率的UI表現(xiàn)
  • 高頻率變化的UI可以拉起低頻率變化的UI表現(xiàn)

如上圖的放射線部分,它實際是由兩張不同的放射線圖上下疊加而成。下層的放射線順時針轉(zhuǎn)動,上層的放射線逆時針轉(zhuǎn)動。
由于上層的放射線作為表現(xiàn)的主體所以采取了“好”的設(shè)置(分辨率高、非壓縮),那么作為表現(xiàn)的襯托部分的下層圖,就算采用比較“不好”的設(shè)置(分辨率低,壓縮),也不容易察覺。
所以,針對這種多UI同時或同位置出現(xiàn)的情況,可以酌情調(diào)低某些UI的設(shè)置。
當(dāng)然,這個例子中,上下兩層采取同一張高品質(zhì)的圖也是解決方案之一。

輸出圖片的分辨率可以酌情低于視網(wǎng)膜的分辨率

本方法能為GPU、外存、內(nèi)存帶來好處

從iPhone4開始興起了視網(wǎng)膜級別的PPI。這讓手機(jī)的任意App的任意界面的任意一幀,都看不出任何像素感,提高了App的用戶體驗。
但在游戲中,游戲有以下特點:

  • 游戲的UI資源是獨立原創(chuàng)的(App的UI資源有可能直接使用操作系統(tǒng)自帶的資源,節(jié)省外存),會帶來非??陀^的外存、內(nèi)存消耗
  • 游戲是動態(tài)的
  • 游戲的一幀內(nèi),最吸引玩家眼前的往往是一個局部
  • 再根據(jù)上面提到的“好”的UI可以拉起“不好的”UI的表現(xiàn)

所以在游戲中,可以酌情將特定非重點的UI圖片的分辨率降低。


輸出圖片的分辨率可以酌情低于視網(wǎng)膜的分辨率

繼續(xù)以上圖為例,獲得的黃金物品作為表現(xiàn)的主體之一,是視網(wǎng)膜分辨率的。但它下面的彈出框背景作為表現(xiàn)襯托,采取了低于視網(wǎng)膜分辨率也察覺不出。

去除UI圖片中不必要的通道、不必要的區(qū)域

本方法能為GPU、外存、內(nèi)存帶來好處

去除UI圖片中不必要的通道、不必要的區(qū)域

如上圖。地球UI圖片是沒必要有透明通道的,因為它一直以整張底圖的形式存在于游戲。
地圖UI圖右部是可以斟酌是否需要存在的,因為它在游戲中一直都被帶有背景的排名列表UI擋住。

UI圖片一般情況下都不需要mipmap

本方法能為外存、內(nèi)存帶來好處

mipmap會生成多張小圖來避免縮小圖片時沒必要的采樣消耗

mipmap會生成多張小圖來避免縮小圖片時沒必要的GPU采樣消耗。但使用mipmap的圖片會比不使用的圖片多占用約三分之一的外存和內(nèi)存。
由于《獨立防線》項目以iPhone4作為目標(biāo)分辨率進(jìn)行制作,且認(rèn)為此分辨率是需支持的最小分辨率,也就是說,UI圖片很少有縮小的情況出現(xiàn),所以《獨立防線》項目的UI圖片都不需要mipmap,減少沒必要的外存、內(nèi)存消耗。
其他項目如果需兼容更低分辨率的設(shè)備,則要按需選擇mipmap。

多張UI圖片可以打包在一起

本方法能為GPU帶來極大好處,但可能為外存、內(nèi)存帶來壞處

操作很簡單,選擇需要打包的圖了之后,在屬性面板里鍵入任意同一英文字符串(比如這里的PackUIBattle)就好了。

在Unity多圖打包的方法:在Packing Tag加上英文字符串

這樣了之后,多張圖被打包在一張圖里面。

多張UI圖通過SpritePacker的打包結(jié)果

由于多張圖片打包在了一起,根據(jù)上面提過的合并drawcall的原因,會大幅減少這些圖片帶來的GPU消耗。
但從上圖也可以看出,打包之后,會產(chǎn)生多余的透明區(qū)域,所以打包可能帶來的壞處就是增大了外存、內(nèi)存。
所以,關(guān)鍵是選擇哪些圖片進(jìn)行打包。來規(guī)避透明區(qū)域的出現(xiàn)。選擇規(guī)則如下:

  • 不用的圖不打包。因為打包的圖,就算從不使用,也還是會進(jìn)入到最終的ipa或者apk里;
  • 小的圖盡可能打包
  • 大圖(比如大于512x512,常見的有UI底圖)不打包。因為大圖會很有可能產(chǎn)生透明區(qū)域;
  • 降低需要打包中的分辨率最大的圖。

不打包的單張UI圖片分辨率必須是偶數(shù)、很有可能需要是2的N次冪

本方法能為GPU、外存、內(nèi)存帶來好處

按照上面的多張UI圖片可以打包在一起做了之后,不打包的圖應(yīng)該是少量的。
但由于這些圖是獨立存在于內(nèi)存,所以有更嚴(yán)格的要求:

  • 單張UI圖片分辨率必須是偶數(shù)。
  • 單張UI圖片當(dāng)有以下任一特點時,分辨率必須是2的N次冪
  • 需壓縮的單張UI圖片。
  • 需tiled的單張UI圖片。tiled即圖片平鋪,常用于四方連續(xù)UI圖。
  • 需mipmap的單張UI圖片。即多層圖片。一般情況下,UI的圖片都不需mipmap,所以不用考慮這個。

@程序同學(xué):現(xiàn)在大部分移動設(shè)備GPU是支持非2的N次方的。即NPOTSupport.Full或者Restricted的。Full的GPU對任意分辨率的紋理都能直接訪問;Restricted的GPU,一般情況下對任意分辨率的紋理都能訪問,但對于mipmap、tiled的紋理會把它pad成POT。
所以,mipmap、或tiled的非打包單張紋理需強(qiáng)制POT
筆者身邊的紅米、三星、華為等手機(jī),都支持NPOTSupport.Full,只發(fā)現(xiàn)小米3支持NPOTSupport.Restricted,小米3W支持NPOTSupport.Full。

@程序同學(xué):
ETC1(4bit/pixel)成功壓縮要求不帶透明通道(ETC1的編碼block為4x4像素,ETC1編碼時會自動把分辨率補(bǔ)為4的倍數(shù)),否則將以16bit/pixel的方式壓縮保存;PVRTC成功壓縮的要求是POT且方形,否則將以true color(32bit/pixel)不壓縮保存。常用的方案是,把UI圖片打包到一張大圖,且大圖同時滿足ETC1和PVRTC的要求,即POT、且透明通道拆分到大圖的下半部、且方形。
這需要有特殊的shader對這張大圖進(jìn)行采樣:RGB取原本uv、A取uv向下偏移0.5。下半部的Alpha部分可以把Alpha值除以3平均分部到RGB通道,采樣時把RGB相加作為Alpha,這樣有利于ETC1壓縮的效果。
因大圖的制作需要上半部是UI圖片的RGB部分、下半部是UI圖片的Alpha部分。所以需要自研或獲取適合的atlas算法對UI圖片進(jìn)行排版。此時上面提到的Unity自帶的Sprite Packer方法將不再適用。
排版后的大圖的可容忍浪費分辨率是原圖的16bit/4bit=4倍,或32bit/4bit=8倍。
注,PVRTC本可不拆Alpha,以RGBA4bit壓縮,但這樣往往UI紋理視覺效果太差。所以PVRTC可以也拆分Alpha,以“RGBA8bit”=RGB4bit+RGB4bit方式壓縮,視覺效果可以接受。而且這樣恰好和ETC1紋理的流程一致。即ETC1和PVRTC的結(jié)果是都拆Alpha,但它們拆Alpha的原因不一樣。

打包的UI圖片的分辨率可以是任意的

但依然推薦輸出偶數(shù)分辨率,避免未來帶來不可知的麻煩。

UI最好能用九宮格+局部裝飾實現(xiàn)

本方法能為GPU、外存、內(nèi)存帶來好處

Unity UGUI支持直接使用Sprite Editor直接進(jìn)行九宮格制作

九宮格已經(jīng)是非常常用的UI制作方法。
九宮格UI幾乎是百利無一害,所以希望UI同學(xué)能用九宮格的盡量用九宮格。
使用九宮格有以下幾個值得注意的技巧:

  • 九宮格UI圖片可以做得很小只給正方形的圖,而并非上面一個長條形的圖
  • 如果UI圖片內(nèi)部是低頻變化(人話:比較平滑的紋理),依然可以使用九宮格
  • 如果UI圖片內(nèi)部是高頻變化(人話:比較細(xì)的復(fù)雜紋理),一般情況下就不能使用九宮格了
  • 但可以把這些高頻變化的紋理設(shè)計成只在邊緣出現(xiàn),讓九宮格十字架內(nèi)依然是低頻變化,那這種UI圖依然可以九宮格
  • 切九宮格時,邊緣部分應(yīng)盡量細(xì)、內(nèi)部十字架部分應(yīng)該盡量飽滿。這樣可以確保這個UI能夠使用于非常小的場合而不穿幫

字體選擇方案

本方法能為外存、內(nèi)存帶來好處,可能為GPU帶來好處

在選擇游戲字體的時候,除了確保美觀程度之外,還需考慮:

  • 字體種類:應(yīng)當(dāng)保持在2類以內(nèi):用于標(biāo)題的中文偏設(shè)計的字體、用于正文的中文偏正式的字體。如需,可額外加入英文偏設(shè)計的字體;
  • 字體編碼類型:如果是中文字體,需考慮是否GB2312編碼甚至是GBK編碼。避免字體出現(xiàn)有些常用中文字沒有的情況;
  • 在選擇字體時,應(yīng)留意在手機(jī)上的表現(xiàn)。比如一些字體比較細(xì),在手機(jī)上看不清,到后面需要都加粗加描邊,帶來沒必要的消耗,也帶來了之后額外的繁瑣的字體相關(guān)工作。
由于選擇了細(xì)字體,導(dǎo)致在手機(jī)上需要都加粗加描邊,帶來沒必要的消耗(比如overdraw)

制作流程

UI同學(xué)和程序同學(xué)一起維護(hù)Unity UI資源文件夾

當(dāng)前的工作流程是美術(shù)同學(xué)輸出了UI圖片后,傳到FTP,通知程序同學(xué)具體路徑,程序同學(xué)從FTP拷貝資源到UnityUI資源文件夾,為了版本一致,程序同學(xué)可能需要對它進(jìn)行重命名,才用上了一張新資源。

Unity UI資源文件夾里存放著真正采用到游戲的文件夾
這個文件夾事實上已經(jīng)存在了,但只有程序同學(xué)在維護(hù)?,F(xiàn)在需要UI美術(shù)同學(xué)、程序同學(xué)一起來維護(hù)它。
這樣有以下好處:

  • Unity的文件夾里,可以直接存放任意格式的圖片甚至是psd。Unity在構(gòu)建時才將這些圖片轉(zhuǎn)為需要用的格式
  • 可以直接在Unity看到圖片在手機(jī)里內(nèi)存、外存的真正占用
  • 方便查找真正在用的UI資源
  • 由于這個文件夾的資源是正式且確保資源不重復(fù),所以方便美術(shù)同學(xué)間協(xié)作,防止信息不對稱制作了重復(fù)資源
  • 當(dāng)有UI小幅修改時,美術(shù)直接修改即可。而不是走一個美術(shù)修改、傳給程序、程序替換的臃腫流程
  • 給資源重用落地提供基礎(chǔ)

事實上,我們的特效、場景、模型都已經(jīng)是這樣做了,一起維護(hù)一個真正采用到游戲的文件夾

資源組件重用

老生常談、不得不談。
資源重用可以節(jié)省策劃同學(xué)工作量、美術(shù)同學(xué)工作量、程序同學(xué)工作量,節(jié)省外存、內(nèi)存,也節(jié)省用戶體驗學(xué)習(xí)成本,。
如果減法百利無一害,何必狂做加法吃力不討好。

Flash項目可重用貼圖的資源庫

Unity項目可重用貼圖的資源庫

一個可以幫助資源重用的思考流程大致是這樣的:

  1. UI美術(shù)同學(xué)如果在接到新UI需求;
  2. 先想UI的某個組件能不能用資源庫里已有UI資源組件來完成
  3. 如果能,則重用,僅僅在Photoshop里制作示意圖,不輸出該UI組件資源(此時,如果可以形成工具和規(guī)則,幫助UI美術(shù)同學(xué)將psd導(dǎo)出成prefab,將有效提高UI合入效率?!丢毩⒎谰€》項目組正在往這個方向嘗試);
  4. 如果不能,才設(shè)計新UI組件資源;同時,新資源也遵循可重用規(guī)則;
  5. 新資源歸檔回資源庫;
  6. 多次重復(fù)1-5步后,資源庫會越來越容易滿足未來的新UI的需求。

適配設(shè)備分辨率的UI制作思路

接近16:9的iPhone5(1136 x640)的關(guān)卡界面
接近1:1的iPad Retina(2048x1536)的關(guān)卡界面

最近新出的手游為了更好的體驗,都采取了填滿設(shè)備屏幕的分辨率適配的UI方案。所以要求策劃同學(xué)、UI同學(xué)在設(shè)計時,就要考慮分辨率適配問題。而并不能僅僅瞄準(zhǔn)一款熱門設(shè)備比如iPhone5進(jìn)行設(shè)計。

Unity UGUI有很好的UI適配方案。概括描述如下:

矩形的原點都在左下角。
3個重要的矩形:實在存在的父矩形、用于輔助的anchor矩形、實在存在的子矩形(當(dāng)前矩形)
父矩形內(nèi)部包含了anchor矩形和子矩形。

下列圖中,外框表示父矩形、“四葉花瓣尖”組成anchor矩形、藍(lán)點表示子矩形。

圖:anchor矩形四角跟父矩形四角一一對應(yīng)。即歸一化距離(即距離占父矩形寬或高的比例)固定。對應(yīng)的兩個角之間就好像用**橡皮筋**綁起來一樣。比如圖中左上花瓣跟左上角距離總是50%寬、60%高。注意到,圖中anchor矩形四角聚在一起,這樣父矩形大小變化時,anchor矩形大小不會變化。
圖:anchor矩形四角跟父矩形四角一一對應(yīng)。對應(yīng)的兩個角之間的歸一化距離(即距離占父矩形寬或高的比例)固定。對應(yīng)的兩個角之間就好像用**橡皮筋**綁起來一樣。比如圖中左上花瓣跟左上角距離總是10%寬、50%高。注意到,圖中anchor矩形四角各自分開,這樣父矩形大小變化時,anchor矩形大小也會變化。
圖:子矩形四角跟anchor矩形四角一一對應(yīng)。對應(yīng)的兩個角之間的距離固定。對應(yīng)的兩個角之間就好像用**鐵棒**鎖起來一樣。比如圖中左上藍(lán)點跟左上花瓣的距離總是80像素寬、30像素高。注意到,圖中anchor矩形四角聚在一起,這樣父矩形大小變化時,由于anchor矩形大小不會變化,所以子矩形大小不會變化。
圖:子矩形四角跟anchor矩形四角一一對應(yīng)。對應(yīng)的兩個角之間的距離固定。對應(yīng)的兩個角之間就好像用**鐵棒**鎖起來一樣。比如圖中左上藍(lán)點跟左上花瓣的距離總是40像素寬、20像素高。注意到,圖中anchor矩形四角各自分開,這樣父矩形大小變化時,由于anchor矩形大小也會變化,所以子矩形大小也會變化。

總之,anchor矩形四角跟父矩形四角一一對應(yīng),對應(yīng)的兩個角之間的歸一化距離(即距離占父矩形寬或高的比例)固定;子矩形四角跟anchor矩形四角一一對應(yīng)。對應(yīng)的兩個角之間的距離固定。

通過這樣的關(guān)系,就可以實現(xiàn)各種不同的適配方案。比如以下這些。

當(dāng)四花瓣聚在一起時,父矩形改變大小,子矩形大小不會改變。位置會鎖定在歸一化距離。


橫向縱向皆不拉伸

當(dāng)四花瓣格子橫向分開時,父矩形改變大小,子矩形橫向大小會相應(yīng)改變。


橫向拉伸、縱向不拉伸

當(dāng)四花瓣格子橫向縱向皆分開時,父矩形改變大小,子矩形橫向縱向大小皆會相應(yīng)改變。


橫向縱向皆拉伸
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容