很多人在做基于Unity的移動遊戲開發時,對很多細節的忽略導緻了最終遊戲性能的低下,并且在最終需要做優化的過程中也并不覺得很多問題是需要被優化的。
這些問題在性能強勁的PC機上沒問題的,但在移動硬體如此低下的今天還是會産生較大問題。現在将問題羅列如下:
1 将需要使用的屬性查詢緩存起來
在Unity中transform.position并不是一個簡單的屬性查詢,Unity會調用附加函數來傳回其值,是以回來帶額外開銷。
當平凡在Update中使用時,請緩存該屬性。
2 不要頻繁使用Instantiate和Destroy
這個建議來至Unity官方的移動開發優化建議,對于GameObject的建立開銷Unity并沒有自信,對于比較複雜的Object會産生較大的開銷,是以建議使用緩存池的方式來初始化GameObject。
3 不要建立過于龐大的緩存池
依然來至于Unity官方的建議,這個問題主要是為了提醒開發者不要因為上一條建議而濫用了緩存池。正确的緩存池建立應該基于真實應用中進行調節,比如:有一個sprite最多可能需要用到100個,但80%的情況下隻需要用到20個,此時初始化建立的緩存池中隻需要建立20個,其餘的在使用後建立并放入緩存池。在緩存池的建立時,設定一個最大值,當需要緩存的物件超過池子大小時,删除使用頻率較少的物件。
4 習慣性的将暫時不用的GameObject設定為非激活
5 從項目的第一天開始就開始用Profiler來監控
很多時候,可能優化的隻是一個“bug”。
容易忽略的美術資源的優化:
優化的美術制作真是一種感覺和經驗的積累,能看出制作水準的不是做的效果多麼犀利,而是得看制作的效果與對機器的要求等的成本效益。
- 關于合并: 100個三角形的MESH,在渲染時與1500個面數的物體是沒太大差别的,最佳的渲染設定應該在每個模型大約1500-4000個三角面。
- 材質共享: 如果需要通過腳本來通路複用材質屬性,改變Renderer.material将會造成一份材質的拷貝。應該使用Renderer.sharedMaterial來保證材質的共享狀态。
- 批處理動态物體需要在每個頂點上進行一定的開銷,也有一些限制:
-
- 對VB的顯存大小也有一定限制,如果着色器使用頂點位置,法線和UV值三種屬性,那麼隻能批處理300頂點以下的物體;如果着色器需要使用頂點位置,法線,UV0,UV1和切向量,那隻能批處理180頂點以下的物體了。
- 擁有lightmap的物體含有額外(隐藏)的材質屬性,比如:lightmap的偏移和縮放系數等。是以,擁有lightmap的物體将不會進行批處理(除非他們指向lightmap的同一部分)。
- 使用不同縮放(scale)的物體将不能批次。分别擁有縮放尺度(1,1,1)和(2,2,2)的兩個物體将不會進行批處理。
- 另外一個值得吸收的經驗是非均勻縮放動畫在unity中非常的慢,均勻縮放會快很多。
- 骨骼數量控制:一般來說遊戲中的骨骼數量為15-60個。骨骼越少運作速度越快,一般來說30塊骨骼就可以讓角色動的很舒服了。建議每個角色30個骨骼,就按照這個規範吧。
- 嘗試用壓縮貼圖格式,或用16位代替32位。
程式開發層面的注意點:
- 垃圾回收器收集垃圾記憶體時負載較大,對移動裝置是個大問題,是以要從代碼層面減少臨時記憶體的生成,
1) 移除代碼中的任何字元串連接配接,因為這會給GC留下大量垃圾。
2) 用簡單的“for”循環代替“foreach”循環。由于某些原因,每個“foreach”循環的每次疊代會生成24位元組的垃圾記憶體。一個簡單的循環疊代10次就可以留下240位元組的垃圾記憶體。
3) 更改我們檢查遊戲對象标簽的方法。用“if (go.CompareTag (“Enemy”)”來代替“if (go.tag == “Enemy”)”
- 使用#pragma strict 簡單的添加#pragma strict在腳本頂部,之後Unity将禁用腳本的動态類型,強制你使用靜态類型。
- 緩存各種元件、Object查找
- 盡量使用固定的内置數組:内置數組是非常快的。ArrayList或Array類很容易使用,更友善使用。但是他們有完全不同的速度。内置數組還有好處是,記憶體連續,元素對齊。
- 不要使用System,System.Xml以及其他系統自帶的DLL,會多出幾兆空間,找找開源的。
- 盡量采用内置的高效的shader吧,例如(built-in)Shader mobile,如果自己寫,複雜的數學計算函數别用,alphatest慎重(美術幾何挖洞來實作吧)。shader中注意float/half/fixed的使用。