Unity3D遊戲優化方案
阿新 • • 發佈:2019-01-05
淺談Unity3D專案優化
作為一個入行不足三年的攻城獅來講,講引擎中的優化,經驗確實不足,unity3D引擎作為一款側重移動端遊戲開發引擎來講,優化遊戲是確實有必要的,畢竟他要適配所有機型的前提下又要保證遊戲畫面的清晰度,特效的絢麗多彩,所以國內大部分遊戲公司都要喜歡招收既會碼程式碼又會做優化的複合人才。
廢話不多說,直接上方案。
效能優化
1.CPU優化
1.DrawCalls
新版Unity也可以叫DrawCall,定義:Unity每次在準備資料並通知GPU渲染的過程稱為一次DrawCall,顯示在工程中就是Batches的大小,Batches越大,畫面越是卡頓,不流暢。
通常來說,如果是在pc端釋出的遊戲,DrawCall應該控制在2000以內,如果是要釋出到移動端,那麼DrawCall最大不能超過300,越低越好,當然在保證畫面質量的前提下。那麼如何降低DrawCall呢,我在這裡說兩種最常用的方法,第一種:靜態批處理Batching Static,批處理相同材靜態獨享或者相同紋理的靜態物件,直接上圖。
2.動態批處理
即是批處理非靜態物件,但是要求苛刻,稍作修改就會批處理不成功,我建議大家使用靜態批處理
物理元件
1.設定一個合適的FixedTimestep.
Editor-ProjectSetting-Time,開啟可以根據需求動態設定。
2.不要使用MeshCollder,從優化角度來看,儘量減少物理元件的使用。
MeshCollider顧名思義,即是網格碰撞器,如果非要使用,建議大家使用Meshbaker網格合併,合併碰撞器,這一點我設計的有些少發一個連結,大家可以參考一下。
3.GC(Garbage Collection垃圾回收)
處理器-排程->GC回收垃圾。
在我們做需要大量生成和銷燬遊戲物件的遊戲時,如FPS類遊戲,如果頻繁例項化Instantiate和Destroy,則會大量排程GC,從而嚴重消耗CPU效能,在這裡,我就可以使用物件池模式來減少GC的排程,何為物件池呢,物件池就是存放需要被反覆呼叫資源的一個空間,當一個物件會大量生成的時候,如果每次都銷燬建立,會非常浪費時間,通過物件池把暫時不用的物件放到一個池子中(也就是一個集合中),當下次要重新生成這個物件的時候,先去池子中查詢一下是否有可用的物件,如果有就直接拿出來使用,如果沒有,就重新建立,利用空間換時間來達到遊戲的告訴執行,減少GC的排程。大家可以參考我物件池的連結,學習一下。
連結
另外降低GC的方案如下,1減少New產生物件的次數,2,使用公共的物件(靜態成員),3.將String換成StringBundle.都可以減少GC的排程,4儘量不用foreach,而是用for,foreach會涉及到迭代器的使用,每一次迴圈所產生的迭代器會帶來24bytes的垃圾,迴圈10次,就是240bytes。5.不要直接訪問gameobject的tag屬性,訪問物體的tag屬性會在堆上額外的分配空間。6.LinQ->連線資料庫。
程式碼質量
1.不要頻繁的使用GetComponent,尤其在迴圈中。
2.善於使用OnBecameVisible()he1OnBecameInVisible().
3.使用內建的陣列,如Vecter.Zero而不是new Vector3(0,0,0).
4.善於使用ref關鍵字
5.將經常需要使用的屬性查詢快取起來。
6.不要頻繁使用Instantiate和Destroy,使用物件池。
7.習慣性的將暫時不用的GameObject設定為非啟用,即使把
GPU的優化
兩種方案:1.減少繪製的數目,2.優化視訊記憶體頻寬。
如何減少繪製的數目
1.保持材質的數目儘可能少,這使得unity更容易進行批處理。
2.使用紋理影象,來代替一些列單獨的小貼圖。
3.如使用了紋理影象和共享材質,使用Render.SharedMaterial代替Render.material。
4.使用光照紋理,Lightmap,而非實時燈光,這一點尤為重要,但是操作起來不難,我在這裡著重講解。
首先,如果是一個加了大量的燈光和粒子特效,即使是一個小小的塔防遊戲,DrawCall也會達到5000以上甚至更高,這是為什麼呢,是因為燈光和粒子特效需要GPU實時渲染,燈光和粒子特效的數量越多,DrawCall也就越高。但是我們場景中的燈光是不需要實時渲染的,如果你場景中的燈光很多時,就只需要下面的操作就可以大大降低DrawCall,優化GPU。
首先開啟unity中的Windows面板-Light-選擇Lights,然後把Baking選擇為Baked型別,右下角Auto勾去掉,選擇Build等待烘焙完畢即可,如下圖所示
大家需要實際操作一下,當然需要實時渲染的燈光不要要烘焙,問題不大。
5.使用LOD,LOD即是遠的看不清的物體的細節忽略,當靠近他時才讓渲染他的細節,說白了就是物體在遠處時,雖然我們的肉眼看不清,但是相機還是在渲染他的所有細節,這是不需要的,此時我們可以使用LOD,把精細的模型換成粗模,一次來減少GPU的渲染,具體操作如下圖所示。
6.遮擋剔除。
1.當場景中包含大量模型時,造成渲染效率的降低(即幀速率FPS的降低),採用遮擋剔除技術,可以使得那些被阻擋的物體不被渲染提高渲染效率
2.原理:在場景空間中建立一個遮擋區域,該遮擋區域是有單元格(Cell)組成;每個單元格是構成整個場景遮擋區域的一部分,這些單元格會把整個場景拆分成多個部分,當攝像機能夠看到該單元格時,表示該單元格的物體會被渲染出來,其他的不去渲染
3.遮擋剔除步驟:
(1)場景
(2)除了主角,攝像機,直線光,地面。把層級檢視中的所有遊戲物件標記為“遮擋靜態”(Occluder Static/Occludee Static)
(3)執行選單命令“Windows”—>“Occlusion Culling”,彈出“遮擋剔除”面板,單擊下方的“Back”按鈕,開始烘焙
(4)單擊“遮擋剔除”(Occlusion)視窗的“Visualizatior”,執行程式
4.若場景中存在大量的小“物件”,使用“層消隱距離”來優化場景
(1):原理:較遠距離將小物件剔除,減少繪圖呼叫的數量
(2):方法:將小物件放入一個單獨的層(Separate Layer)中,並使用Camera.main.layerCullDistances函式設定層的消隱距離
(3)例如:void Start(){
Float[] distances=new float[32];
//這裡定義的陣列下標“8”表明第8層
distances[8]=10;
Camera.main.layerCullDistances=distances;
}
當攝像機距離這些小物件超過10m的時候,就不可見了
7.使用mobile版的shader。
具體操作入下,新建一個mateiral,inspector-Shader-Mobile-選擇需要的型別,適合移動端的釋出,pc端也可以使用,包括天空盒也可以使用。
優化視訊記憶體頻寬
1.OpenGL ES 2.0使用ETC1格式壓縮等等,在打包設定哪裡都有這些選項,點選選擇即可。
2.MipMap技術
MipMap是把圖片處理成預先計算好的比較小的圖集,在在螢幕尺寸變小時呼叫處理好的小圖,以此來節約GPU渲染,但是缺點是會增加33%的圖集記憶體,因為原圖還要儲存。
Unity3D內部的優化
1.Resources 資源不用的要刪除,紋理,網格,音訊,元件等等。
2.在CPU壓力不是很大的時候,重置GameObject,元件等佔用的記憶體。
3.在打AssetBundle的時候,可以考慮bundle的壓縮等等。
以上為本人近兩年工作中所用到的所有優化技術方案,希望對大家有所幫助,謝謝。