1.對於DrawCall的認識:
DrawCall即爲由CPU下達命令,調用OpenGL或DirectX接口進行解析並由GPU進行渲染顯示的過程稱爲一次DrawCall。
在Unity中查看DrawCall參數,Window / Profiler 或者Ctrl+7 快捷鍵打開 Profiler性能分析器面板。
在程序運行狀態,如下圖即爲DrawCall參數:
當然,在保證遊戲流暢度的基礎上DrawCall越小越好!
2.Statistics統計面板的認識:
在程序運行狀態下,Game窗口點擊Stats打開統計面板,參數如下:
FPS(幀數):越大越好
CPU(處理器計算速度):越低越好
render thread(渲染線程,GPU渲染所需要的時間):越低越好
Batches(渲染批次):與DrawCall關聯,是Unity自動分類的渲染批次
Tris(三角面數):相機視野範圍內的三角面數量
Verts(頂點數):相機視野範圍內的頂點數量
SetPass calls:Unity中的Shader中包含很多Pass塊,每當GPU即將去運行一個Pass塊之前,就會產生一個“SetPass call”,在描述性能開銷上更有說服力
3.資源優化:
Mesh方面:
動態模型:
面片數<3000, 材質數<3, 骨骼數<50
靜態模型:
頂點數<500
Audio方面:
長時間音樂(背景音樂)壓縮格式:mp3
短時間音樂(攻擊等等)一般不壓縮存儲格式爲:wav
導入到Unity後的編輯面板顯示爲:
Decompress On Load:適用於小文件
Compressed in Memory:使用於大文件
Streaming:以流的形式便加載邊播放(對CPU消耗較大一般不採用)
Texture方面:
貼圖長度<1024(對手機而言)
Shader方面:
儘量減少複雜的數學運算
儘量減少Discard操作
減少冗餘資源和重複資源方面:
A.Resources目錄下的資源不管是否被引用,都會打包進安裝包,不使用的資源不要放在Resources目錄下
B.不同目錄下的相同資源文件,如果都被引用,那麼都會打包進資源包,造成冗餘,保證同一個資源文件在項目中只存放在一個目錄位置
4.LOD層級細節技術:
此技術需要美工的配合,提供給程序多個不同三角面數的模型
在場景中新建一個空的遊戲物體,並添加LOD Group組件,如下圖所示:
並將美工提供的三種不同精度的模型按照精度的大小依次拖入到LOD0、LOD1、LOD2中
此時,場景中渲染顯示的模型會根據相機與模型的距離進行切換顯示,具體的切換顯示距離可拖動組件中的條形框大小進行自定義,這樣便達到了近處渲染精模,遠處渲染粗模甚至不渲染來減少GPU消耗的目的
5.OcclusionCulling遮擋剔除技術:
當場景中有大量模型需要渲染時,應用遮擋剔除可實現減少DrawCall提升性能的效果
首先選中所有需要進行遮擋剔除的模型,並設置其occluder(遮擋體)和occludee(被遮擋體),有的物體可以是遮擋體同時也是被遮擋體。
接下來Window / Occlusion Culling 打開遮擋剔除面板如下圖:
選中遮擋剔除選項,烘焙
烘焙完成後,設置好顯示視野的相機
6.Lightmapping光照貼圖技術:
首先將需要進行光照貼圖的遊戲物體設置爲Lightmap Static
其次將用於光照貼圖的所有光源設置爲Baked模式
最後Window / Lighting 打開燈光面板,進行烘焙,面板如下
其中Build後會在當前場景所在的文件夾中生成一個光照貼圖文件,我們也可以點擊Clear Baked Data 按鈕進行光照貼圖的清理操作
之後無論場景中的光源是否激活,均顯示光照效果,效果圖如下:
·
7.Mesh合併:
當場景中模型非常多,不妨試一下模型合併技術,可以在3dMax或其他建模軟件上進行操作,也可在Unity中進行操作,這裏我僅介紹Unity中的模型合併方法。
前提:合併的物體必須是相同的材質,否則合併之後賦值多個材質並不能起到優化作用
首先,將下述代碼放在Assets / Editor 文件夾下
其次,在場景中需要合併的模型放在一個空物體下
然後,點擊選中空物體並點擊上方的菜單欄按鈕MeshCombine / CombineChildren進行合併所有子物體Mesh
最後,自行更改模型中的材質,位置等參數即可
using UnityEngine;
using System.Collections;
using UnityEditor;
public class CombineMesh : MonoBehaviour {
//菜單按鈕靜態觸發
[MenuItem( "MeshCombine/CombineChildren")]
static void CreatMeshCombine()
{
//獲取到當前點擊的遊戲物體
Transform tSelect = (Selection.activeGameObject).transform;
//如果當前點擊的遊戲物體無子物體,則無操作
if (tSelect.childCount < 1)
{
return;
}
//確保當前點擊的遊戲物體身上有MeshFilter組件
if (!tSelect.GetComponent<MeshFilter>())
{
tSelect.gameObject.AddComponent<MeshFilter>();
}
//確保當前點擊的遊戲物體身上有MeshRenderer組件
if (!tSelect.GetComponent<MeshRenderer>())
{
tSelect.gameObject.AddComponent<MeshRenderer>();
}
//獲取到所有子物體的MeshFilter組件
MeshFilter[] tFilters = tSelect.GetComponentsInChildren<MeshFilter>();
//根據所有MeshFilter組件的個數申請一個用於Mesh聯合的類存儲信息
CombineInstance[] tCombiners = new CombineInstance[tFilters.Length];
//遍歷所有子物體的網格信息進行存儲
for (int i = 0; i < tFilters .Length ; i++)
{
//記錄網格
tCombiners[i].mesh = tFilters[i].sharedMesh;
//記錄位置
tCombiners[i].transform = tFilters[i].transform.localToWorldMatrix;
}
//新申請一個網格用於顯示組合後的遊戲物體
Mesh tFinalMesh = new Mesh();
//重命名Mesh
tFinalMesh.name = "tCombineMesh";
//調用Unity內置方法組合新Mesh網格
tFinalMesh.CombineMeshes(tCombiners);
//賦值組合後的Mesh網格給選中的物體
tSelect.GetComponent<MeshFilter>().sharedMesh = tFinalMesh;
//賦值新的材質
tSelect.GetComponent<MeshRenderer>().material = new Material(Shader.Find("VertexLit"));
}
}
效果圖如下:
8.資源池的利用:
當有遊戲物體需要頻繁的創建刪除的時候,不妨試試資源池,可以節約性能。
例子:射擊遊戲中的子彈。
源鏈接:轉自博客園——魔卡先生
只爲學習與知識分享!如有侵權,請聯繫刪除!