關於Unity性能優化的一些方法

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.資源池的利用:

  當有遊戲物體需要頻繁的創建刪除的時候,不妨試試資源池,可以節約性能。

  例子:射擊遊戲中的子彈。

源鏈接:轉自博客園——魔卡先生

只爲學習與知識分享!如有侵權,請聯繫刪除!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章