該遊戲在CPU占用方面的性能非常不錯,下圖為該遊戲在紅米Note2裝置上進行一場5V5戰鬥時的性能資料。

可以看出,在紅米Note2上運作的19876幀中,超過33ms的幀數占比為13.9%,超過50ms的幀數占比為1.7%,并且從圖中可以看出,其CPU耗時較高處主要集中在5V5場景的資源加載階段。是以,該遊戲在戰鬥時的性能可以說是非常優秀,絕大多數時刻遊戲運作非常流暢。
同時,通過進一步統計,該遊戲的CPU性能超過了64%的同裝置(紅米Note2)上測試的其他遊戲,其能耗更是低于86%的同裝置測試遊戲。由于目前國内的MOBA遊戲較少,是以上述排名并不是在MOBA類型中的排名,而是在所有類型遊戲中的排名。對于一款超重度的MOBA移動遊戲來說,該CPU性能和能耗排名可以說是相當出色。
其整體CPU性能的優秀表現與其各個子產品的合理使用是分不開的。下面,我們就詳細講解其CPU性能方面的亮點之處。
1、渲染子產品
通過UWA性能測評報告,我們可以看到該遊戲詳盡的渲染子產品性能開銷。該遊戲在紅米Note2裝置上運作時的渲染子產品CPU開銷如下圖所示。通過統計,半透明物體渲染的CPU消耗均值為1.7 ms,主要集中在0.8~3.0 ms範圍内(5%~95%)。不透明物體渲染的CPU消耗均值為1.0 ms,主要集中在0.2~1.7 ms範圍内(5%~95%)。可以看出,在整個5V5戰鬥過程中,無論是移動、Farm、Gank還是團戰,甚至上高地時,其渲染耗時都穩定在一個較低的耗時區間。這得益于研發團隊對于場景模型、蒙皮網格和UI的控制十分得當。
Draw Call峰值為167,且主要集中在 45~130範圍内(5%~95%),渲染三角形面片單幀峰值為64900,以上數值均處于合理範圍之内。
2、UI子產品
該遊戲在紅米Note2裝置上運作時的UI子產品CPU開銷如下圖所示。該遊戲使用UGUI作為UI界面的解決方案。經過統計,UI子產品總體的CPU占用均值為1.5 ms,主要集中在0.1~3.5 ms(5%~95%),屬于合理範圍之内。堆記憶體累積配置設定為16000幀 2.4MB,平均每幀配置設定堆記憶體155.4B,這說明該遊戲UI界面的制作及UI重建的影響範圍非常合理。目前,UWA推薦UGUI子產品中,平均每幀堆記憶體配置設定盡可能控制在200B以下。
戰鬥場景中,UI系統的性能耗時主要是由UI元素的狀态變化而導緻的,比如血條、飄字等HUD的移動、消隐等。這種操作稍不注意,就會帶來較高的UI網格重建開銷。是以,UI界面的研發看似直覺、簡單,但是其對于制作時的層層考究和運作時的耐心調優,則是一款産品是否“匠心”的試金石。以下則為《小米超神》這款産品在經過幾輪優化後的UI性能對比圖。
3、動畫子產品
在UWA測評報告中,該遊戲運作時的動畫子產品CPU開銷如下圖所示。可以看出,除進入場景時出現CPU高值外,其在戰鬥副本中的CPU開銷均控制在較低水準。Animator.Update的CPU均值為2.0 ms,主要集中在0.1~4.3ms區間内,對于MOBA項目5V5場景來說,基本上每幀均有90-130個物體在進行運動(除英雄、小兵之外,還有信使寵物、野怪、塔、插眼等等),由于玩家可以随意檢視地圖上任何一個角落的特點,其每幀的動畫系統壓力要比正常的MMO遊戲大上數倍。是以,《小米超神》可以将其控制在均值2.0ms的水準線上,已經是非常優秀的資料了。
同時,經過進一步檢測發現,動畫子產品的耗時主要由Animators.ProcessAnimationsJob和Animators.FireAnimationEventsAndBehaviours導緻,前者主要是持續的累積耗時,而後者則是非連續的“尖刺”開銷。前者是動畫系統對于AnimationClip的讀取和計算耗時所緻,其耗時大小與目前幀參與計算的骨骼節點數、動畫曲線數、動畫執行狀态和Animator Controller的具體設定相關,其具體說明可參見《Unity中動畫系統性能優化方案回顧》;後者則是動畫事件的具體耗時,主要是項目邏輯代碼的性能開銷,此處研發團隊可以通過性能堆棧來進一步檢視其邏輯代碼的開銷是否有進一步的優化空間。
4、GC 調用
該研發團隊對于GC調用頻率控制得非常出衆,遊戲在運作過程中,GC調用頻率為1656幀/次,優于目前93%的行業内遊戲。一般來說,我們建議一款項目的GC調用頻率可以控制在1000幀/次以上。
該遊戲的GC調用頻率如此優秀,主要得益于研發團隊對于項目代碼堆記憶體的控制。下圖為遊戲運作20000幀的代碼堆記憶體具體配置設定情況,其Top10函數的堆記憶體配置設定總和不超過80MB,足見該團隊對于堆記憶體配置設定的了解非常深刻。
目前版本的堆記憶體配置設定仍然有進一步下降的空間,從堆棧資訊中可以看到,其Log輸出仍然存在一定堆記憶體配置設定,建議研發團隊在Release版本中将非關鍵性Log進行屏蔽。
《小米超神》在記憶體上的表現如下圖所示。總記憶體峰值達到297MB,Mono堆記憶體峰值為48.9MB。297MB的總記憶體配置設定相對來說略高,研發團隊可嘗試在低記憶體機器上對資源進行進一步控制,進而降低低記憶體機器上的記憶體占用。
1、Mono堆記憶體
從下圖可知,該遊戲的總體Mono堆記憶體控制得很好,在20000幀中,Mono的堆記憶體峰值為48.9MB,該值略高(UWA建議<40MB)。從圖中看,是戰鬥最後上高地時突然出現了較高的堆記憶體配置設定,迫使Mono堆記憶體上漲了8MB(如下圖紅框所示),對此,研發團隊可以根據具體位置檢視其堆記憶體配置設定,即可定位其具體的堆記憶體配置設定根源。
但是,從走勢上來看,其Used Mono堆記憶體占用在5V5戰鬥結束後,并未完全回落到場景之前(如藍框所示),這一點需要引起研發團隊注意,确認其是否為部分指定容器緩存所緻,進而排查項目是否存在堆記憶體洩露的隐患。
2、資源記憶體
經過統計,該遊戲運作時的紋理資源數量峰值為1003個,記憶體占用峰值54.8MB。研發團隊将紋理記憶體占用控制得很低,目前僅高于30%的行業項目。經過統計,在記憶體占用峰值處,ETC1和ETC2格式紋理占有835個,RGBA32格式紋理共占有89個,RGB24格式紋理占有5個,其餘為RGBA16格式紋理。
紋理資源在項目運作期間的總體使用情況:
對于紋理資源的優化,一般可分為以下幾種:
(1)使用更合适的紋理格式
從上圖中可以看到,在整個遊戲一場5V5戰鬥過程中,RGBA32格式紋理的使用數量較多,其使用總量已經超過了91%的的行業項目。對此,我們建議在視覺效果可以保證的情況下,盡可能使用ETC1格式紋理(Android平台)進行替換,不僅可以達到更小的記憶體占用,同時可以獲得更快的加載效率。而對于無法進行硬體壓縮的紋理,可以通過Dither方法嘗試将其轉換成RGBA16格式的紋理,具體做法可以參考Unity圖檔優化神器 - Dither算法進階方案。
(2)使用更精準的紋理分辨率
一般來說,為了讓模型看上去更加精美,除Mesh模型本身以外,其對應的紋理都會選用較高的紋理尺寸,進而讓其看上去更加精緻。但是,由于渲染物體在真正的遊戲中相對于相機是有遠近之分的,其顯示卡底層往往沒有(或根本不需要)使用如此高的分辨率來進行渲染,進而就造成了大量的資源浪費,這在我們深度優化過的項目中比比皆是。是以,我們建議可以通過UWA線上測評報告中GPU性能的Mipmap功能頁面來直接檢視遊戲運作時,其底層的紋理分辨率使用情況,如下圖所示。
同時,在深度優化報告中,我們也會進行更大量的測試和幾十億像素累積分析,進而來精準指出到底哪些紋理資源的分辨率制作過高,可在不影響視覺效果的前提下,将其分辨率縮小4倍、16倍甚至更多。《小米超神》項目通過這種方式不斷優化,其5V5場景的紋理記憶體已經從之前的78MB降到了現在的52MB。
以上是紋理資源的使用情況,其他資源的記憶體占用情況如下:
網格資源在項目運作期間的總體使用情況:
Mesh資源的記憶體占用較高,高于60%的行業項目。對于Mesh資源記憶體的優化,主要有以下幾種方法:
(1)控制網格頂點屬性的使用
詳細檢測網格模型中的Color資料和Tangent資料,當不需要時切記要将其進行去除,否則會在場景模型拼合時産生大量的記憶體浪費,具體詳細說明可以參考《移動遊戲加載性能和記憶體管理全解析》。
(2)控制網格頂點的數量
詳細檢測網格模型的頂點數(或面片數)使用是否過大。這是一個說起來容易但實施起來很難的問題,其難點在于如何定義一個Mesh網格的頂點數是否過大。在UWA測評報告中會有一個建議,即建議将Mesh網格頂點數控制在1500個以下。但實際上,這其實是一個“不科學”的規定,因為沒有任何一個理論可以證明,其網格數量大于1500就是不合格,或則小于1500就一定合格。是以,我們這一年來花了大量的時間來尋求一種更為合理、科學的判斷規則。我們認為判斷一個網格模型使用是否合規并不應該是“靜态”檢測,而應該是一種“動态”檢測,與上述紋理資源的檢測一樣,我們應該去看網格資源在底層渲染時到底占據了多少像素,進而以一種密度統計的方式來判斷其網格使用量是否合理。是以,我們提出了一種網格模型測量标準,即“網格模型渲染密度”,其表示每機關數量(比如,1萬)像素中,其網格模型的渲染頂點數量。
下圖則為遊戲運作過程中的網格模型渲染密度統計值。可以看出,雖然第一個模型“Mod_xyc_fz1001”的頂點數僅為1168,但其在遊戲運作時平均每幀的渲染像素量僅為34.91個,也就是說平均每個像素要渲染33個網格頂點,這顯然是一種浪費。是以,通過“渲染密度”這一檢測方式,可以反映任何一個模型在遊戲運作時的使用情況。在我們來看,這是一個比單純設定1500更加合理的判斷規則。
AnimationClip資源在項目運作期間的總體使用情況:
AnimationClip的記憶體占用較高,高于76%的全類型遊戲項目。對于一款MOBA項目來說,其記憶體占用較高是可以了解的,因為其戰鬥副本中擁有大量的動畫模型,比如英雄、小兵、野怪、塔、基地等建築等等。對此,僅能建議研發團隊嘗試從數量上進行進一步地縮減,以降低其記憶體的使用。同時,對于卡通片段記憶體的一般優化還有“縮減精度”、“使用Humanoid類型”等方法,其具體優化方法可以參考《Unity中動畫系統性能優化方案回顧》。
該遊戲在資源執行個體化/銷毀、Active/Deactive等方面做的非常出色!在遊戲運作的20000幀中,Instantiate和Destroy調用次數分别為1653次和4019次,而Active和Deactive調用次數則分别為116次和1447次。同時,對于Instantiate和Destroy操作來說,其主要調用均在進出戰鬥場景處,副本中雖有Instantiate調用,但無論是頻率還是CPU耗時,均處于合理範圍之内,如下圖所示。
對于GameObject相關的資源管理,我們的建議如下:
(1)對項目中存在頻繁Instantiate/Destroy操作的GameObject一定要進行大力徹查,下圖即為某一項目的Instantiate執行個體化詳情,我們建議對于紅框處高頻率和耗時的操作重點排查,因為其無論是CPU還是堆記憶體都對項目性能造成非常大的殺傷力!
(2)頻繁的Active/Deactive操作不僅會造成CPU的浪費,同時,它還很可能間接造成更大的CPU耗時,比如Animator.Initialize耗時。在此,我們不妨看下另一款遊戲的Animator.Initialize調用情況,如下圖所示,其調用的頻率和耗時較高,這就是頻繁的Active/Deactive操作所造成的結果。是以,對于GameObject不必要的Active和Deactive操作進行控制,是非常有必要的。更為詳細的資源加載性能優化總結,可參見《Unity移動遊戲加載性能和記憶體管理全解析》。
(3)不斷檢測、不斷完善,優化是一個需要不斷疊代、持之以恒的事情。下圖則為《小米超神》經過幾輪優化之後的資源管理變化情況。
以上則為《小米超神》遊戲在CPU性能和記憶體管理方面的具體使用情況。優秀的CPU性能、非常少的堆記憶體配置設定以及引擎子產品間的合理使用,足以看出該研發團隊非常深厚的技術功底和對于引擎相當優秀的把控能力。
最後,非常感謝《小米超神》研發團隊對 UWA 的認可和支援。感謝他們樂意将項目性能資料與大家一起分享,讓更多的研發團隊了解到一款性能優秀的MOBA手遊在各個子產品上應該做到怎樣的程度。同時,也希望更多的開發團隊可以與我們一起來分享他們的性能資料,讓更多的遊戲開發者受益!
原文出處:侑虎科技
本文作者:admin
轉載請與作者聯系,同時請務必标明文章原始出處和原文連結及本聲明。