(整理總結)unity效能優化
一 減少Draw call
Draw call就是cpu對圖形繪製介面的呼叫,CPU通過呼叫圖形庫(directx/opengl)介面,命令GPU進行渲染操作。
每一次繪製CPU都要呼叫DrawCall,呼叫DrawCall之前,CPU要進行很多準備工作:檢測渲染狀態,提交渲染所需要的資料,提交渲染所需要的結果,當DrawCall過多CPU會有很多額外的開銷用於準備工作,CPU負載,GPU限制。
解決方案:把小的DrawCall合併為一個大的DrawCall中,這就是批處理思想。
使用批處理的注意事項:
合併的網格會在一次渲染任務中進行繪製,他們的渲染資料,渲染狀態和shader都是一樣的,因此合併的條件至少是:同材質、同貼圖、同
儘量避免使用大量小的網格,當確實需要時,考慮是否要合併。
避免使用過多的材質,儘量共享材質。
網格合併的頂點數量有上限(Unity中好像是65535)
合併本身有消耗,因此儘量在編輯器下進行合併
確實需要在執行時合併的,將靜態的物體和動態的物體分開合併:靜態的合併一次就可以,動態的只要有物體發生變換就要重新合併。
在unity選單欄window-profiler可以看專案性能資料:
二 資源優化
優化標準:
Mesh
動態模型:面片數材質數<3
骨骼數<50
靜態模型:定點數<500
長時間音樂(背景音樂)壓縮格式mp3
短時間音樂(音效)非壓縮格式wav(例如戰鬥音效,如果壓縮,攻擊一次就需要壓縮一次)
貼圖長寬<1025
Shader
減少複雜數學運算
減少discard操作
一貼圖優化:
二模型優化:
減少頂點數量
三減少冗餘資源和重複資源:
1.Resources目錄下不管資源是否被使用都會被打包
2.不同目錄下的相同資原始檔,如果被引用,那麼大寶都會打包進資源包
3.保證同一個資原始檔在專案中只存放在一個目錄位置
相關文件:
三 渲染優化
一 LOD層級讓模型在視野的不同範圍內顯示不同精度的模型,距離越遠模型越粗糙,渲染越簡單。
在屬性面板新增LOD Group元件,設定攝像機視野顯示的模型。
具體細節設定在Edit-projectsetting-QualitySetting
在攝像機視野範圍內的渲染顯示,不在範圍內的不渲染顯示
1. 全選要進行遮擋剔除的物體
2. 在static裡面選中OcclusionCulling Static屬性
3. 在Window-Occlusion Culling中設定烘焙,選擇目標攝像機
三 光照貼圖
把環境的光照效果提前計算好,生成一張光照貼圖,這樣以後就不需要再去實時渲染環境的光照效果
1.選擇環境,再static裡面選擇lightmap Static
2.在window-Lightting-setting設定烘焙
3.在資原始檔夾中會生成光照貼圖資訊,彩色的一個屬性圖示
四 網格合併
把多個物體合併成為一個大的物體,需要通過程式碼實現,把要合併的物體放到一個物體下面作為子物體:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshCombiner : MonoBehaviour {
// Use this for initialization
void Start () {
MeshCombine();
}
void MeshCombine()
{
MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();
CombineInstance[] combiners = new CombineInstance[filters.Length];
for(int i = 0; i < filters.Length; i++)
{
combiners[i].mesh = filters[i].sharedMesh;
combiners[i].transform = filters[i].transform.localToWorldMatrix;
}
Mesh finalMesh = new Mesh();
finalMesh.CombineMeshes(combiners);
GetComponent<MeshFilter>().sharedMesh = finalMesh;
}
四 其他優化
一 物件池 當有物體大量重複出現時可以使用物件池去優化,例如子彈,每此扣動扳機都要射出一發子彈,例項化一個子彈,太浪費效能,這時候就可以去使用物件池解決。 二 程式碼編寫1.儘量不要動態的instantiate和destroy object,使用object pool
2.儘量不要再update函式中做複雜計算,如有需要,可以隔N幀(FixedUpdate)計算一次
3.不要動態的產生字串,如Debug.Log("boo" + "hoo"),儘量預先建立好這些字串資源
4.cache一些東西,在update裡面儘量避免search,如GameObject.FindWithTag("")、GetComponent這樣的呼叫,可以在start中預先存起來
5.儘量減少函式呼叫棧,用x = (x > 0 ? x : -x);代替x = Mathf.Abs(x)
三 其他優化博文