推薦閱讀:
Unity 優化(一) ------ 優化前瞭解以及方向
FPS:畫面每秒傳輸幀數,,要避免動作不流暢的最低是30;值越大性能越好
CPU:計算每幀需要消耗的時間,值越低說明計算越快,值越小性能越好
Batches:將某些DrawCalls合併,數量爲合併後DrawCall的數量。
Tris:三角面
Verts:頂點
SetPass call:Shader中Cpu每次運行Pass之前都會產生一個SetPass call。
Unity 優化(二) ------ 資源優化
長時間音樂使用Mp3格式(使用壓縮格式),例如:背景音樂等
短時間音樂使用wav格式(不使用壓縮格式),例如:音效
減少冗餘資源和重複資源
A、Resources目錄下的資源不管是否被引用,都會打包進安裝包
不使用的資源不要放在Resources目錄下
B、不同目錄下的相同資源文件,如果都被引用,那麼都會打包進資源包,造成冗餘
保證同一個資源文件在項目中只存放在一個目錄位置
資源優化:使用UWA工具
渲染優化(GPU)和代碼優化(CPU)
GPU:包括場景渲染和燈光處理等
CPU:數值計算
LOD——層級
當模型離視野近時,顯示比較精細的模型,離視野比較遠時顯示比較粗糙的模型。
實現方法:
新建一個空物體,添加LOD Group組件,將模型拖進精細度按下圖提示拖進對應位置,可根據實際情況調節每個LOD的佔比。
遮擋剔除
目的;降低DrawCall
原理:在攝像機視野內的物體顯示,在視野外的物體不顯示。
實現方法:
(1)在場景中創建很多物體(方便觀察)。全選中—點擊Static—Occluder Static
(2)點擊Windows—Occlusion Culling
(3)選擇指定相機用於遮擋剔除計算
光照貼圖
目的:降低Batches
實現方法:
(1)搭建好場景,選中場景中所有需要被光照的物體—點擊Static—LightmapStatic
(2)點擊Windowa—Lighting—Settings
(3)選擇需要被烘焙的光源,將模式選擇烘焙模式
(4)Scene—取消勾選—Generate Lighting
(5)選擇烘焙後,下方是烘焙進度
(6)選擇所有被烘焙的光源,取消Light勾選
這時還能看見光照效果,這時因爲使用烘焙,生成了光照貼圖
注意:如果覺得光照強度過強,在(4)前可修改
Light組件中Indensity值,值越低,光照越暗
合併Mesh
要求合併的mesh使用相同的材質。
實現方法:
(1)創建一個空物體MeshCombine,併爲其創建幾個子物體,子物體層級任意
(2)新建腳本並掛在到(1)中的空物體MeshCombine上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MeshCombine : MonoBehaviour {
// Use this for initialization
void Start () {
CombineMesh();
}
void CombineMesh()
{
MeshFilter[] filters = GetComponentsInChildren<MeshFilter>();//獲取空物體下所有子物體的MeshFilter組件並保存爲一個數組
CombineInstance[] combiners = new CombineInstance[filters.Length];//unity提供的一個類,用於處理合並的實例
//將filters的一些屬性設置給combiners
for (int i = 0; i < combiners.Length; i++)
{
combiners[i].mesh = filters[i].sharedMesh;
combiners[i].transform = filters[i].transform.localToWorldMatrix;//這裏的transform不是一個組件而是一個矩陣轉換,用於世界座標與局部座標之間的轉換
}
Mesh finalMesh = new Mesh();
finalMesh.CombineMeshes(combiners);//合併mesh
GetComponent<MeshFilter>().sharedMesh = finalMesh;//將合併後的Mesh賦值到父物體上
}
}
(3)爲(1)中的空物體MeshCombine 添加兩個組件:
MeshRender組件:負責渲染
MeshFilter組件:用於存放合併後的mesh
並未MeshRender組件選擇一個需要的材質。
(4)遊戲運行,會將MeshCombine下的所有子物體中的Mesh合併並賦值到MeshCombine物體上,因此場景中將會出現兩個一模一樣的mesh,這時在遊戲運行時可直接刪除其下的子物體,這時可明顯看見Batches減少。
ObjectPool
對象池的使用可以說是非常常見。直接上代碼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObjectPool : MonoBehaviour {
public int objCount=5;//對象池中該類對象初始生成的個數
public GameObject buttlePreb;//需要實例化的預製
private List<GameObject> poolList = new List<GameObject>();//存放對象
void Start () {
InitPool();
}
//初始化對象池
void InitPool()
{
for (int i = 0; i < objCount; i++)
{
GameObject go = Instantiate(buttlePreb);//實例化對象
poolList.Add(go);//將實例化的對象添加到對象次
go.SetActive(false);//設置爲隱藏—即未被使用
}
}
//從對象池中取對象
public GameObject ShowObj()
{
foreach (GameObject go in poolList)
{
if (!go.activeInHierarchy)
{
go.SetActive(true);
return go;
}
}
return null;
}
//使用協程,使得對象生成後等待指定時間隱藏—即放回對象池
public IEnumerator HideObj(GameObject go)
{
yield return new WaitForSeconds(3);
go.SetActive(false);
}
}
使用對象池:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class startBuntle : MonoBehaviour {
private ObjectPool objPool;
void Start () {
objPool = GetComponent<ObjectPool>();
}
void Update () {
if (Input.GetKeyUp(KeyCode.K))
{
GameObject go = objPool.ShowObj();
if (go != null)
{
//對象次還有可用對象
go.GetComponent<Rigidbody>().velocity = transform.forward * 30;
StartCoroutine(objPool.HideObj(go));
}
}
}
}