基於Unity3d 引擎的Android遊戲優化
最近專案進入收尾階段,之前對專案做了很多優化,mesh合併 ,減少DrawCall和模型骨骼以及物理計算,合併材質球,優化程式碼等等,在IOS上還好,但是Android上,試過幾款手機,從低端到高階,發現效能還是很差,所以又花了幾天來研究摸索,終於把遊戲效能搞定。記錄下來,留作以後參考。
1. 更新不透明貼圖的壓縮格式為ETC 4bit,因為android市場的手機中的GPU有多種,每家的GPU支援不同的壓縮格式,但他們都相容ETC格式,
2. 對於透明貼圖,我們只能選擇RGBA 16bit 或者RGBA 32bit。
3. 減少FPS,在ProjectSetting-> Quality中的VSync
這兩種情況都不符合遊戲的FPS的話,我們需要手動調整FPS,首先關閉垂直同步這個功能,然後在程式碼的Awake方法裡手動設定FPS(Application.targetFrameRate = 45;)
降低FPS的好處:
1)省電,減少手機發熱的情況;
2)能都穩定遊戲FPS,減少出現卡頓的情況。
4. 當我們設定了FPS後,再調整下Fixed timestep這個引數,這個引數在ProjectSetting->Time中,目的是減少物理計算的次數,來提高遊戲效能。
5. 儘量少使用Update LateUpdate FixedUpdate,這樣也可以提升效能和節省電量。多使用事件(不是SendMessage,使用自己寫的,或者C#中的事件委託)。
6. 待機時,調整遊戲的FPS為1,節省電量。
Unity3D中新建一個場景空的時候,幀速率(FPS總是很低),大概在60~70之間。一直不太明白是怎麼回事,現在基本上明白了。我在這裡解釋一下原因,如有錯誤,歡迎指正。在Unity3D中當執行場景開啟Profiler的時候,我們會看到VSync 這一項佔了很大的比重。這個是什麼呢,這個就是垂直同步,稍後再做解釋。我們可以關閉VSync
現在來說說什麼是垂直同步,要知道什麼是垂直同步,必須要先明白顯示器的工作原理,顯示器上的所有影象都是一線一線的掃描上去的,無論是隔行掃描還是逐行掃描,顯示器都有兩種同步引數——水平同步和垂直同步。
什麼叫水平同步?什麼叫垂直同步?
垂直和水平是CRT中兩個基本的同步訊號,水平同步訊號決定了CRT畫出一條橫越螢幕線的時間,垂直同步訊號決定了CRT從螢幕頂部畫到底部,再返回原始位置的時間,而恰恰是垂直同步代表著CRT顯示器的重新整理率水平。
為什麼關閉垂直同步訊號會影響遊戲中的FPS數值?
道理一點都不復雜,首先我們平時執行作業系統一般螢幕重新整理率是多少?大概一般都是在85上下吧,那麼顯示卡就會每按照85的頻率時間來發送一個垂直同步訊號,訊號和訊號的時間間隔是上兩次螢幕更新的時間間隔。
如果我們選擇等待垂直同步訊號(也就是我們平時所說的垂直同步開啟),那麼在遊戲中或許強勁的顯示卡迅速的繪製完一屏的影象,但是沒有垂直同步訊號的到達,顯示卡無法繪製下一屏,只有等85單位的訊號到達,才可以繪製。這樣FPS自然要受到作業系統重新整理率執行值的制約。
而如果我們選擇不等待垂直同步訊號(也就是我們平時所說的關閉垂直同步),那麼遊戲中作完一屏畫面,顯示卡和顯示器無需等待垂直同步訊號就可以開始下一屏影象的繪製,自然可以完全發揮顯示卡的實力。但是不要忘記,正是因為垂直同步的存在,才能使得遊戲程序和顯示器重新整理率同步,使得畫面更加平滑和穩定。取消了垂直同步訊號,固然可以換來更快的速度,但是在影象的連續性上勢必打折扣。這也正是很多朋友抱怨關閉垂直後發現畫面不連續的理論原因。
1、頂點效能
一般來說,如果您想在iPhone 3GS或更新的裝置上每幀渲染不超過40,000可見點,那麼對於一些配備 MBX GPU的舊裝置(比如,原始的iPhone,如 iPhone 3g和 iPod Touch第1和第2代)來說,你應該保證每幀的渲染頂點在10000以下。
2、光照效能
畫素的動態光照將對每個受影響的畫素增加顯著的計算開銷,並可能導致物體會被渲染多次。為了避免這種情況的發生,您應該避免對於任何單個物體都使用多個畫素光照,並儘可能地使用方向光。需要注意的是畫素光源是一個渲染模式(Render Mode)設定為重要(Important)的光源。畫素的動態光照將對頂點變換增加顯著的開銷。所以,應該儘量避免任何給定的物體被多個光源同時照亮的情況。對於靜態物體,採用烘焙光照方法則是更為有效的方法。
3、角色
每個角色儘量使用一個Skinned Mesh Renderer,這是因為當角色僅有一個 Skinned Mesh Renderer 時, Unity 會 使用可見性裁剪和包圍體更新的方法來優化角色的運動,而這種優化只有在角色僅含有一個 Skinned Mesh Renderer 時才會啟動。角色的面數一般不要超過1500,骨骼數量少於30就好,角色Material數量一般1~2個為最佳。
4、靜態物體
對於靜態物體定點數要求少於500,UV的取值範圍不要超過(0,1)區間,這對於紋理的拼合優化很有幫助。不要在靜態物體上附加Animation元件,雖然加了對結果沒什麼影響,但是會增加CPU開銷。
5、攝像機
將遠平面設定成合適的距離,遠平面過大會將一些不必要的物體加入渲染,降低效率。另外我們可以根據不同的物體來設定攝像機的遠裁剪平面。Unity 提供了可以根據不同的 layer 來設定不同的 view distance ,所以我們可以實現將物體進行分層,大物體層設定的可視距離大些,而小物體層可以設定地小些,另外,一些開銷比較大的實體(如粒子系統)可以設定得更小些等等。
6、DrawCall
儘可能地減少 Drawcall 的數量。 IOS 裝置上建議不超過 100 。減少的方法主要有如下幾種: Frustum Culling , Occlusion Culling , Texture Packing 。 Frustum Culling 是 Unity 內建的,我們需要做的就是尋求一個合適的遠裁剪平面; Occlusion Culling ,遮擋剔除, Unity 內嵌了Umbra ,一個非常好 OC 庫。但 Occlusion Culling 也並不是放之四海而皆準的,有時候進行 OC 反而比不進行還要慢,建議在 OC 之前先確定自己的場景是否適合利用 OC 來優化; Texture Packing ,或者叫 Texture Atlasing ,是將同種 shader 的紋理進行拼合,根據 Unity 的 static batching 的特性來減少 draw call 。建議使用,但也有弊端,那就是一定要將場景中距離相近的實體紋理進行拼合,否則,拼合後很可能會增加每幀渲染所需的紋理大小,加大記憶體頻寬的負擔。這也就是為什麼會出現“ DrawCall 降了,渲染速度也變慢了”的原因。