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

極端的體驗

極端的性能(從2015年的標準來看)
在手游平臺上,我們應該追求的是體驗和性能平衡。

體驗和性能的平衡
性能評估標準
游戲中,任一元素(UI圖片、特效、模型等)對性能的影響都可以拆分為以下4種影響。

影響性能的4大方面
現(xiàn)就UI相關(guān)的影響進行舉例如下。
CPU消耗
CPU負責把UI界面的邏輯結(jié)構(gòu)進行更新、匯總,并負責把這些數(shù)據(jù)準備好。最后把這些信息傳給GPU。
UI一般影響CPU的因素包括:
界面結(jié)構(gòu)復雜度
界面結(jié)構(gòu)變化頻率
動畫復雜度

復雜的界面結(jié)構(gòu)
GPU消耗
GPU負責最終畫面的繪制、渲染。因為渲染是復雜的流程、且運算量巨大、且手機GPU固有的硬件限制(核心數(shù)少、浮點運算速度慢),手游的性能瓶頸往往都發(fā)生在GPU。
也就是說,GPU消耗是性能優(yōu)化的重中之重。
UI一般影響GPU的因素包括:
繪制次數(shù)(drawcall),和單張圖片的數(shù)量等因素相關(guān)
圖片最終在屏幕所展現(xiàn)的面積
圖片是否透明
shader的復雜度
重繪度(overrdraw,單位像素的重新繪制次數(shù))
其中,特別值得注意的是drawcall和重繪復雜度。
drawcall
每一個不同“材質(zhì)”的東西都需要占用一個drawcall。每多一個drawcall必然帶來額外的CPU消耗和GPU消耗。

UI界面的drawcall次數(shù)為125次
可以簡單認為,當兩個東西的材質(zhì)的shader相同,且紋理相同,則它們是同一個材質(zhì),在渲染它們的時候,引擎會進行優(yōu)化,會合并drawcall為1個。
overdraw

overdraw健康的UI界面

overdraw不健康的UI界面
overdraw表示單位像素的重新繪制次數(shù)
右部表示overdraw的程度,越“亮”的區(qū)域表示overdraw的程度越高,也就越消耗GPU。
外存消耗
外存消耗指的是資源在用戶“硬盤里占用了多少多少M”。
如果外存過大,可能導致用戶不愿意下載,或者下載安裝后,硬盤空間不夠,安裝不成功。
一般影響外存的因素包括:
圖片數(shù)目
圖片的分辨率大小
圖片是否壓縮
另外,優(yōu)化了外存,內(nèi)存往往也會從中受益。
內(nèi)存消耗
內(nèi)存消耗指的是“游戲在實際運行時,占用多少M”。
如果內(nèi)存過大,可能會導致用戶游戲體驗不流暢,甚至crash。
一般影響內(nèi)存的因素包括:
圖片數(shù)目
圖片的分辨率大小
圖片的分辨率是否是2的N次方,
圖片是否壓縮
UI制作要點
UI輸出的圖片,可在Unity里設置為新的等比縮放分辨率
正因如此,UI美術(shù)同學在輸出UI貼圖時,一般情況下按美術(shù)示意圖的原分辨率輸出即可。

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

輸出圖在Unity里被設置為寬高不超過512
單獨調(diào)分辨率的工作,目前是由開發(fā)同學進行。最理想的工作流程,是UI美術(shù)同學在導圖到Unity的時候,就單獨按需設置分辨率(和特效場景模型同學的工作流程一樣)。
至于什么情況下需要進行降分辨率操作,見下文。
低頻變化的圖片的分辨率可以很小
本方法能為GPU、外存、內(nèi)存帶來好處
低頻變化的圖片指的是純色的、漸變等變化比較平緩的圖片。
低頻變化的圖片拉伸后仍能表現(xiàn)非常類似的效果,這是因為GPU在圖片采樣時會進行相鄰像素的插值,從而能大概還原之前的平滑度。
總而言之,低頻變化的圖片的分辨率可以很小。
實例如下。

低頻變化圖片:原圖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)的主體所以采取了“好”的設置(分辨率高、非壓縮),那么作為表現(xiàn)的襯托部分的下層圖,就算采用比較“不好”的設置(分辨率低,壓縮),也不容易察覺。
所以,針對這種多UI同時或同位置出現(xiàn)的情況,可以酌情調(diào)低某些UI的設置。
當然,這個例子中,上下兩層采取同一張高品質(zhì)的圖也是解決方案之一。
輸出圖片的分辨率可以酌情低于視網(wǎng)膜的分辨率
本方法能為GPU、外存、內(nèi)存帶來好處
從iPhone4開始興起了視網(wǎng)膜級別的PPI。這讓手機的任意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作為目標分辨率進行制作,且認為此分辨率是需支持的最小分辨率,也就是說,UI圖片很少有縮小的情況出現(xiàn),所以《獨立防線》項目的UI圖片都不需要mipmap,減少沒必要的外存、內(nèi)存消耗。
其他項目如果需兼容更低分辨率的設備,則要按需選擇mipmap。
多張UI圖片可以打包在一起
本方法能為GPU帶來極大好處,但可能為外存、內(nèi)存帶來壞處
操作很簡單,選擇需要打包的圖了之后,在屬性面板里鍵入任意同一英文字符串(比如這里的PackUIBattle)就好了。

在Unity多圖打包的方法:在Packing Tag加上英文字符串
這樣了之后,多張圖被打包在一張圖里面。

多張UI圖通過SpritePacker的打包結(jié)果
由于多張圖片打包在了一起,根據(jù)上面提過的合并drawcall的原因,會大幅減少這些圖片帶來的GPU消耗。
但從上圖也可以看出,打包之后,會產(chǎn)生多余的透明區(qū)域,所以打包可能帶來的壞處就是增大了外存、內(nèi)存。
所以,關(guān)鍵是選擇哪些圖片進行打包。來規(guī)避透明區(qū)域的出現(xiàn)。選擇規(guī)則如下:
不用的圖不打包。因為打包的圖,就算從不使用,也還是會進入到最終的ipa或者apk里;
小的圖盡可能打包
大圖(比如大于512x512,常見的有UI底圖)不打包。因為大圖會很有可能產(chǎn)生透明區(qū)域;
降低需要打包中的分辨率最大的圖。
不打包的單張UI圖片分辨率必須是偶數(shù)、很有可能需要是2的N次冪
本方法能為GPU、外存、內(nèi)存帶來好處
按照上面的多張UI圖片可以打包在一起做了之后,不打包的圖應該是少量的。
但由于這些圖是獨立存在于內(nèi)存,所以有更嚴格的要求:
單張UI圖片分辨率必須是偶數(shù)。
單張UI圖片當有以下任一特點時,分辨率必須是2的N次冪
需壓縮的單張UI圖片。
需tiled的單張UI圖片。tiled即圖片平鋪,常用于四方連續(xù)UI圖。
需mipmap的單張UI圖片。即多層圖片。一般情況下,UI的圖片都不需mipmap,所以不用考慮這個。
@程序同學:現(xiàn)在大部分移動設備GPU是支持非2的N次方的。即NPOTSupport.Full或者Restricted的。Full的GPU對任意分辨率的紋理都能直接訪問;Restricted的GPU,一般情況下對任意分辨率的紋理都能訪問,但對于mipmap、tiled的紋理會把它pad成POT。
所以,mipmap、或tiled的非打包單張紋理需強制POT。
筆者身邊的紅米、三星、華為等手機,都支持NPOTSupport.Full,只發(fā)現(xiàn)小米3支持NPOTSupport.Restricted,小米3W支持NPOTSupport.Full。
@程序同學:
ETC1(4bit/pixel)成功壓縮的要求是POT且不帶透明通道,否則將以16bit/pixel的方式壓縮保存;PVRTC成功壓縮的要求是POT且方形,否則將以true color(32bit/pixel)不壓縮保存。常用的方案是,把UI圖片打包到一張大圖,且大圖同時滿足ETC1和PVRTC的要求,即POT、且透明通道拆分到大圖的下半部、且方形。
這需要有特殊的shader對這張大圖進行采樣:RGB取原本uv、A取uv向下偏移0.5。下半部的Alpha部分可以把Alpha值除以3平均分部到RGB通道,采樣時把RGB相加作為Alpha,這樣有利于ETC1壓縮的效果。
因大圖的制作需要上半部是UI圖片的RGB部分、下半部是UI圖片的Alpha部分。所以需要自研或獲取適合的atlas算法對UI圖片進行排版。此時上面提到的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īng)是非常常用的UI制作方法。
九宮格UI幾乎是百利無一害,所以希望UI同學能用九宮格的盡量用九宮格。
使用九宮格有以下幾個值得注意的技巧:
九宮格UI圖片可以做得很小只給正方形的圖,而并非上面一個長條形的圖
如果UI圖片內(nèi)部是低頻變化(人話:比較平滑的紋理),依然可以使用九宮格
如果UI圖片內(nèi)部是高頻變化(人話:比較細的復雜紋理),一般情況下就不能使用九宮格了
但可以把這些高頻變化的紋理設計成只在邊緣出現(xiàn),讓九宮格十字架內(nèi)依然是低頻變化,那這種UI圖依然可以九宮格
切九宮格時,邊緣部分應盡量細、內(nèi)部十字架部分應該盡量飽滿。這樣可以確保這個UI能夠使用于非常小的場合而不穿幫
字體選擇方案
本方法能為外存、內(nèi)存帶來好處,可能為GPU帶來好處
在選擇游戲字體的時候,除了確保美觀程度之外,還需考慮:
字體種類:應當保持在2類以內(nèi):用于標題的中文偏設計的字體、用于正文的中文偏正式的字體。如需,可額外加入英文偏設計的字體;
字體編碼類型:如果是中文字體,需考慮是否GB2312編碼甚至是GBK編碼。避免字體出現(xiàn)有些常用中文字沒有的情況;
在選擇字體時,應留意在手機上的表現(xiàn)。比如一些字體比較細,在手機上看不清,到后面需要都加粗加描邊,帶來沒必要的消耗,也帶來了之后額外的繁瑣的字體相關(guān)工作。

由于選擇了細字體,導致在手機上需要都加粗加描邊,帶來沒必要的消耗(比如overdraw)
制作流程
UI同學和程序同學一起維護Unity UI資源文件夾
當前的工作流程是美術(shù)同學輸出了UI圖片后,傳到FTP,通知程序同學具體路徑,程序同學從FTP拷貝資源到UnityUI資源文件夾,為了版本一致,程序同學可能需要對它進行重命名,才用上了一張新資源。
Unity UI資源文件夾里存放著真正采用到游戲的文件夾。
這個文件夾事實上已經(jīng)存在了,但只有程序同學在維護?,F(xiàn)在需要UI美術(shù)同學、程序同學一起來維護它。
這樣有以下好處:
Unity的文件夾里,可以直接存放任意格式的圖片甚至是psd。Unity在構(gòu)建時才將這些圖片轉(zhuǎn)為需要用的格式
可以直接在Unity看到圖片在手機里內(nèi)存、外存的真正占用
方便查找真正在用的UI資源
由于這個文件夾的資源是正式且確保資源不重復,所以方便美術(shù)同學間協(xié)作,防止信息不對稱制作了重復資源
當有UI小幅修改時,美術(shù)直接修改即可。而不是走一個美術(shù)修改、傳給程序、程序替換的臃腫流程
給資源重用落地提供基礎
事實上,我們的特效、場景、模型都已經(jīng)是這樣做了,一起維護一個真正采用到游戲的文件夾
資源組件重用
老生常談、不得不談。
資源重用可以節(jié)省策劃同學工作量、美術(shù)同學工作量、程序同學工作量,節(jié)省外存、內(nèi)存,也節(jié)省用戶體驗學習成本,。
如果減法百利無一害,何必狂做加法吃力不討好。

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

Unity項目可重用貼圖的資源庫
一個可以幫助資源重用的思考流程大致是這樣的:
UI美術(shù)同學如果在接到新UI需求;
先想UI的某個組件能不能用資源庫里已有UI資源組件來完成;
如果能,則重用,僅僅在Photoshop里制作示意圖,不輸出該UI組件資源(此時,如果可以形成工具和規(guī)則,幫助UI美術(shù)同學將psd導出成prefab,將有效提高UI合入效率?!丢毩⒎谰€》項目組正在往這個方向嘗試);
如果不能,才設計新UI組件資源;同時,新資源也遵循可重用規(guī)則;
新資源歸檔回資源庫;
多次重復1-5步后,資源庫會越來越容易滿足未來的新UI的需求。
適配設備分辨率的UI制作思路

接近16:9的iPhone5(1136
x640)的關(guān)卡界面

接近1:1的iPad Retina(2048x1536)的關(guān)卡界面
最近新出的手游為了更好的體驗,都采取了填滿設備屏幕的分辨率適配的UI方案。所以要求策劃同學、UI同學在設計時,就要考慮分辨率適配問題。而并不能僅僅瞄準一款熱門設備比如iPhone5進行設計。
Unity UGUI有很好的UI適配方案。概括描述如下:
矩形的原點都在左下角。
3個重要的矩形:實在存在的父矩形、用于輔助的anchor矩形、實在存在的子矩形(當前矩形)。
父矩形內(nèi)部包含了anchor矩形和子矩形。
下列圖中,外框表示父矩形、“四葉花瓣尖”組成anchor矩形、藍點表示子矩形。

圖:anchor矩形四角跟父矩形四角一一對應。即歸一化距離(即距離占父矩形寬或高的比例)固定。對應的兩個角之間就好像用橡皮筋綁起來一樣。比如圖中左上花瓣跟左上角距離總是50%寬、60%高。注意到,圖中anchor矩形四角聚在一起,這樣父矩形大小變化時,anchor矩形大小不會變化。

圖:anchor矩形四角跟父矩形四角一一對應。對應的兩個角之間的歸一化距離(即距離占父矩形寬或高的比例)固定。對應的兩個角之間就好像用橡皮筋綁起來一樣。比如圖中左上花瓣跟左上角距離總是10%寬、50%高。注意到,圖中anchor矩形四角各自分開,這樣父矩形大小變化時,anchor矩形大小也會變化。

圖:子矩形四角跟anchor矩形四角一一對應。對應的兩個角之間的距離固定。對應的兩個角之間就好像用鐵棒鎖起來一樣。比如圖中左上藍點跟左上花瓣的距離總是80像素寬、30像素高。注意到,圖中anchor矩形四角聚在一起,這樣父矩形大小變化時,由于anchor矩形大小不會變化,所以子矩形大小不會變化。

圖:子矩形四角跟anchor矩形四角一一對應。對應的兩個角之間的距離固定。對應的兩個角之間就好像用鐵棒鎖起來一樣。比如圖中左上藍點跟左上花瓣的距離總是40像素寬、20像素高。注意到,圖中anchor矩形四角各自分開,這樣父矩形大小變化時,由于anchor矩形大小也會變化,所以子矩形大小也會變化。
總之,anchor矩形四角跟父矩形四角一一對應,對應的兩個角之間的歸一化距離(即距離占父矩形寬或高的比例)固定;子矩形四角跟anchor矩形四角一一對應。對應的兩個角之間的距離固定。
通過這樣的關(guān)系,就可以實現(xiàn)各種不同的適配方案。比如以下這些。
當四花瓣聚在一起時,父矩形改變大小,子矩形大小不會改變。位置會鎖定在歸一化距離。

橫向縱向皆不拉伸
當四花瓣格子橫向分開時,父矩形改變大小,子矩形橫向大小會相應改變。

橫向拉伸、縱向不拉伸
當四花瓣格子橫向縱向皆分開時,父矩形改變大小,子矩形橫向縱向大小皆會相應改變。

橫向縱向皆拉伸