U3D 性能優化

官方優化文檔--優化圖像性能
http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

Unity3D性能優化專題
性能優化是一個異常繁瑣而又涉及到項目開發的方方面面的一個過程,它的本質是在運行時的一個時間裏儘量完美展示豐富的內容。
實現優化能夠經過優化資源、渲染、粒子、物理等模式;
也能夠經過修改模型大小、減小紋理尺寸並結合Unity3D的一些相關特性來提高遊戲的性能。
隨着移動端的設備硬件能力的提高,如何使用盡量優化的資源和程序效率來展示出更多的細節內容就成爲了每一個開發者都應該思考的內容,這也使得優化變成了項目開發中很是重要的一環。
***********
首先介紹下draw call(這個東西越少你的遊戲跑的越快):
在遊戲中每個被展現的獨立的部分都被放在了一個特別的包中,咱們稱之爲「描繪指令」(draw call),而後這個包傳遞到3D部分在屏幕上呈現出來。這就和你但願你的親友收到準備好的聖誕禮物須要包裝好而後穿過城市準時放在他應該出現的地方同樣沒什麼不一樣。你的CPU來完成包裝和傳遞他們的活,同時會消耗不少的帶寬,因此最終分配好這些關鍵性資源很重要。目前,真正可怕的事情是從描繪指令消耗遠景開始,每個獨立的飛濺到地板上的血跡和一個角色或者一具死屍消耗的字節是同樣的多的:他們都消耗一樣的描繪指令。除此以外,沒有什麼更多的差異。
那麼如何下降 draw call 呢??那麼咱們就用到Culling(剔除)技術。若是不該用這個技術,電腦是無論3721把場景裏全部的東西都送去渲染的。看得見的也渲染,看不見得照樣也送去渲染。很傻是吧,那咋辦呢。得告訴電腦,那個你
看得見的渲染,看不見的就算了。因而就有了
1.視錐體剔除(Frustum Culling)這個unity系統自帶了好像,就不用操心了。
2.遮擋剔除(Occlusion Culling
Unity 3專業版內置了一個強大的 Occlusion Culling 插件 Umbra免費的
遮擋剔除(Occlusion Culling
遮擋剔除是一種什麼樣的特性呢, 當一個物體被其餘物體遮擋住而不在攝像機的可視範圍內時不對其進行渲染。. 遮擋剔除在3D圖形計算中並非自動進行的。由於在絕大多數狀況下離 camera 最遠的物體首先被渲染,靠近攝像機的物體後渲染並覆蓋先前渲染的物體(這被稱爲重複渲染,無效渲染"overdraw"). 遮擋剔除不一樣於視錐體剔除. 視錐體剔除只是不渲染攝像機視角範圍外的物體而對於被其餘物體遮擋但依然在視角範圍內的物體則不包括在內. 注意當你使用遮擋剔除時你依然受益於視錐體剔除(Frustum Culling.
***********
Unity(或者說基本全部圖形引擎)生成一幀畫面的處理過程大體能夠這樣簡化描述:引擎首先通過簡單的可見性測試,肯定攝像機能夠看到的物體,而後把這些物體的頂點(包括本地位置、法線、UV等),索引(頂點如何組成三角形),變換(就是物體的位置、旋轉、縮放、以及攝像機位置等),相關光源,紋理,渲染方式(由材質/Shader決定)等數據準備好,而後通知圖形API——或者就簡單地看做是通知GPU——開始繪製,GPU基於這些數據,通過一系列運算,在屏幕上畫出成千上萬的三角形,最終構成一幅圖像。
Unity中,每次引擎準備數據並通知GPU的過程稱爲一次Draw Call。這一過程是逐個物體進行的,對於每一個物體,不僅GPU的渲染,引擎從新設置材質/Shader也是一項很是耗時的操做。所以每幀的Draw Call次數是一項很是重要的性能指標,對於iOS來講應儘可能控制在20次之內,這個值能夠在編輯器的Statistic窗口看到。 Unity內置了Draw Call Batching技術,從名字就能夠看出,它的主要目標就是在一次Draw Call中批量處理多個物體。只要物體的變換和材質相同,GPU就能夠按徹底相同的方式進行處理,便可以把它們放在一個Draw Call中。Draw Call Batching技術的核心就是在可見性測試以後,檢查全部要繪製的物體的材質,把相同材質的分爲一組(一個Batch),而後把它們組合成一個物體(統一變換),這樣就能夠在一個Draw Call中處理多個物體了(其實是組合後的一個物體)。
Draw Call Batching存在一個缺陷,就是它須要把一個Batch中的全部物體組合到一塊兒,至關於建立了一個與這些物體加起來同樣大的物體,與此同時就須要分配相應大小的內存。這不只會消耗更多內存,還須要消耗CPU時間。特別是對於移動的物體,每一幀都得從新進行組合,這就須要進行一些權衡,不然得不償失。但對於靜止不動的物體來講,只須要進行一次組合,以後就能夠一直使用,效率要高得多。 - See more at: http://ravenw.com/blog/2011/10/14/unity-optimization-of-draw-call/#sthash.0WfH4KnX.dpuf
***********

輸出設置相關:
1:最終輸出的時候,unity - edit - project setting - player , other settings - script call optimization 改爲 快速, 但沒有例外. fast but no exceptions
2: unity - edit - project setting - time , maximum allowed timestep 改爲0.1
3:

常規優化
1: 聯結(combine)優化
顯卡對於一個含100個面片的物體的和含1500個面片的物體的渲染消耗幾乎是等價的。因此若是你有N個同一材質的東西,那麼把他們聯成同一個物體再統一用一個material那麼對於顯卡的渲染消耗就要下降N倍。
unity裏再聯結,這個要怎麼作呢,其實也挺簡單的,常常看Island Demo項目的人應該很早就注意到裏面的石頭這些都是連在一塊兒的,緣由就在這裏,他提供了現成就腳本實現聯結。
先到Island DemoAssets/Script下找到CombineChildren.csMeshCombineUtility.cs兩個腳本複製到本身的項目文件(咱們要用的只是前者,但他會調用後者,沒有後者unity會報錯,因此把後者扔到項目裏無論就好)
而後把你項目裏那些用同一Materials的東西扔到一個空物體裏面去,再把CombineChildren.cs貼到那個空物體上,搞定!
2: 模型
(1)只用一個mesh renderer, 少用多materials, 最多3
每一個角色儘可能使用一個 Skinned Mesh Renderer
這是由於當角色僅有一個 Skinned Mesh Renderer 時, Unity 會 使用可見性裁剪和包圍體更新的方法來優化角色的運動,而這種優化只有在角色僅含有一個 Skinned Mesh Renderer 時纔會啓動。
(2)模型骨骼不超過30.
(3)儘可能減小面 300-1500
(4)模型儘可能不要分開, 若是多個模塊, 會屢次調用dc
(5)通常角色應該沒有 IK 結點
這是由於角色的動做大多數都是事先設定好的,並不須要通過 IK 操做來進行實時計算( Rogdoll 除外),因此在模型導入時,不要將 IK 結點一塊兒導入。
(6) 不要附加 Animation Component 在靜態實體上附加 Animation 部件雖然對結果沒有影響,但卻會增長必定的 CPU 開銷來調用這一組件,因此儘可能去掉該組件。

3:儘可能不用像素光(pixels Lights)
4:不用 軟陰影(soft shadow), 或者不用陰影(No Shadows)
燈光能不用就不用, 陰影能夠用面來代替.
5:少用實時燈光, 儘可能使用lightmap
http://blog.sina.com.cn/s/blog_409cc4b00100no8y.html
動態實時燈光相比靜態燈光,很是耗費資源。因此除了能動的角色和物體(好比能夠被打的處處亂飛的油桶)靜態的地形和建築,統統使用Lightmap
強大的Unity內置了一個強大的光照圖烘焙工具Beast,這個東東是Autodesk公司的產品
6:transformOnGUI (運算上的優化遠比不上 繪製效率上的優化,少個dc可能就比得上這些了)
http://fredxxx123.wordpress.com/2013/05/22/unity%E6%80%A7%E8%83%BD%E5%84%AA%E5%8C%96%E4%B9%8B%E5%B0%8F%E6%B8%AC%E8%A9%A6/
// transfrom
少用transform, 多用 myCachedTransform
頻繁使用該物件的地方,就是先把該物件cache起來,理論上就會避免這種沒必要的開銷。
※這也可延伸至其餘是property的變數。例如:transform.position
***直接使用的版本:
public class TestUnit : MonoBehaviour
{
void Update()
{
var t = this.transform;
t = this.transform;
t = this.transform;
t = this.transform;
t = this.transform;
}
}
***cache 使用的版本:
public class TestUnit : MonoBehaviour
{
Transform myTransform;
void Start()
{
myTransform = transform;
}

void Update ()
{
var t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
t = this.myTransform;
}
}
// OnGUI
空物件版本:
public class TestUnit : MonoBehaviour
{
}
外加一個空白OnGUI的版本:
public class TestUnit : MonoBehaviour
{
void OnGUI()
{ }
}
實際上是被GUI.Begin()GUI.End()所佔據,function自己是無辜的~~
非必要避免使用OnGUI(),即便它裡面甚麼事情都沒作!
如需使用,請盡可能集中到同一個OnGUI()底下執行繪製,好避免Begin End的開銷。

7:動態物體的相關優化

優化主要分爲兩個方向,一個是資源相關優化和引擎相關的優化。資源相關的優化,大概分爲動態物體、靜態物體、紋理數據、音頻數據、程序包數據。對於動態物體好比NPC、怪物等,須要對面片數量的控制,大概在3002000面。1500面就能夠體現人物細節,但若是是人物比較多,可能要下降面數,不要低於300。另外,一方面是控制Skinned Mesh Renderer的數量;另外一方面是控制材質數量在13種。人物最好用小於30根骨骼,若是你用的骨骼越多,耗費的CPU就更多,因此在移動平臺上儘可能少於30根。如今咱們看其餘動態物體,利用Dynamic Batching進行合批。這個下雨特效並非系統作的,是包含不少雨點的網格進行重複拷貝,而後錯亂移動實現的。每個雨點並非一個粒子,這樣能減小不少CPU的消耗,每個總體網格都會有一個頂點的控制,經過控制頂點數量,對系統實現雨點效果來講,這是一個至關省時省力的方法。

8:靜態物體的相關優化

下面咱們來看靜態物體,靜態物體也是要控制面數和頂點數,頂點數少於500個。static是不會進行移動縮放、旋轉的,把它標記爲static,固然他們的材質是同樣的。不要添加animation組建,對於靜態物體來講,這個組件毫無心義,能把他丟掉就丟掉,由於這對CPU的消耗是很是客觀的。
9:音頻程序的優化
關於音頻時間的播放,好比背景音樂,建議使用MP3壓縮格式,好比音效,要求數據儘快加載,這些數據比較小就能夠,使用WAVAIF未壓縮音頻格式。關於程序包的優化,不少開發者會埋怨說打出來的包太大,如今介紹減小程序包的方法,首先使用壓縮格式的紋理,以顯卡的壓縮格式保存,使用壓縮網格和動畫數據。網格壓縮是先採用量化處理,固然這個壓縮是保證在包裏面的數據小,但運行時佔用的內存沒有減小,由於咱們並無把頂點刪除,可是對動畫數據來講,動畫數據通過壓縮處理後下降,能夠減小遊戲列層。

關於代碼儘可能不要使用System.xml,咱們建議使用Mono.xml。啓用Stripping來減小庫的大小,使用剝離方式。

10:引擎相關優化和物理相關優化
下來是引擎相關的優化,例如光照設置、相繼設置、粒子特效、物理特效等。那拿光照設置來講,光源所有的實時光照這是很恐怖的,每一次實施光照表明着每一次使用消耗,怎麼優化?有人使用LightMapping來製做靜態場景,他的好處是不須要用多張實施光照,而給場景很好的光照效果。有人使用Light Probes代替實時光照,好處是徹底不用怎麼消耗,並且運做性能也很是高。在有些時候使用Light Probes代替光照,他能跟場景很好的融合,在一個角落裏,這個任務會被陰影打得暗一些。若是說場景中確實須要一些實時光源,那麼確定是須要作過優化設置的實時光源,控制important的光源個數。若是說光源有些地方產生了交叉光,這個時候你能夠經過設置Pxel Light,控制每個光源都只接受一個動態光照,數目大概是12個。對於關閉光源的實時陰影,並非全部平臺都支持實時陰影,消耗也很是大,不建議你們使用。關於相機方面的設置,平面越近,渲染越少。咱們更建議使用分層,好比遠處的建築,對於建築物的裁減平面遠一些,若是是花草,就可使用平面就近一些。如今看一下粒子特效,粒子也是遊戲中須要優化的東西,建議屏幕中最大的粒子數不要超過200,同時每一個發射器發射的最大粒子數不要超過50。粒子尺寸也要儘量小,最終在屏幕有多少像素。他們中間的像素可能會被渲染不少次,至少四五次,這時發現粒子系統僅像素就填充了更多屏幕,這時候對遊戲來講很是耗費,對遊戲的其餘功能性能也有所影響。另一方面,對於很是小的粒子,儘可能不要開啓粒子碰撞功能。

如今咱們看一下物理相關優化,物理儘量使用Sphere CoilliderBox Coillider等,儘可能避免使用Meh Colllider等。渲染設置,避免使用Alpha Test,由於很是耗時,性價比很低。關於Sttic Batching,對靜態物體進行Batch,對幾何數據的大小沒有限制。物體被合併後會帶來一些內存消耗,好比說有控制網格的物體,用Batch會合併成大物體。Dynamic Batching目前僅支持小於900頂點的網格物體。如何理解900呢,其實就至關於900個頂點數據大小的物體,若是說使用PositionNormalUV三種屬性,那麼你只能Batch300個頂點。總體縮放的物體不能被Batch,除非他們的縮放值相同。以前有一個客戶作特效,使用Batch機制把面片合併,最終讓全部面片共享一個紋理,這時候發現這些面片沒有被Batch出來,致使運行遊戲時大概放三個技能就10多個招套。對於非總體用戶體,他們的Batch是須要很好利用到。

11:紋理合並優化
如今來看紋理合並,紋理合並就是爲了特到Batch數量,合併物體首先須要合併工具,還要修改使用紋理的網格的UV,使他們使用紋理。合併紋理主要是參照Batch,提升渲染性能。但在合併材質後須要注意的是腳本訪問Renderer被拷貝。/*安擋剔除,建議使用PVS技術。建議你們使用自定義shader,例如高光效果,高光效果可能不須要作一些入射線的檢測,只是簡單把他的值放大也能夠模擬高光效果,從而減小一些消耗。
另一個是用profiler,經過他給的數據進行鍼對性的優化。以上是跟你們介紹優化的內容,如何做出良好優化,必定要作好良好的規劃,到後期就不會很麻煩,若是規劃沒有作好有可能會給程序帶來很大壓力,結果可能很不樂觀。*/最後,要不斷實驗不斷總結才能達到本身滿意的效果。

12:
要想下降Drawcal的話,有以下兩點小建議
1)不要用Unity自帶UI或者iGUI, NUI 或者EZ GUI
(2)建立好的GameObject不用了就最好及時 刪除 / 設置activefalse/移出屏幕 。 這幾種方法均可以去掉該物體致使增長的Drawcall

13:



*********************************
*********************************
*********************************
最近一段時間一直在作Unity IOS設備上的資源優化,結合Unity的官方文檔以及本身遇到的實際問題,我把本身認爲一些重要的信息羅列在下面,並儘量對將其量化,以方便更多須要作優化的朋友。
1、 角色
每一個角色儘可能使用一個 Skinned Mesh Renderer
這是由於當角色僅有一個 Skinned Mesh Renderer 時, Unity 會 使用可見性裁剪和包圍體更新的方法來優化角色的運動,而這種優化只有在角色僅含有一個 Skinned Mesh Renderer 時纔會啓動。
角色 Material 數量
2-3
骨骼數量
小於 30
面片數量
300-1500
通常角色應該沒有 IK 結點
這是由於角色的動做大多數都是事先設定好的,並不須要通過 IK 操做來進行實時計算( Rogdoll 除外),因此在模型導入時,不要將 IK 結點一塊兒導入。
2、 靜態實體
不要附加 Animation Component
在靜態實體上附加 Animation 部件雖然對結果沒有影響,但卻會增長必定的 CPU 開銷來調用這一組件,因此儘可能去掉該組件。
網格頂點數
小於 500
UV 值範圍儘可能不要超過( 0, 1 )區間
儘可能保證 UV 值不越界,這對於未來的紋理拼合優化頗有幫助。
3、 地形
地形的分辨率大小
長寬均儘可能小於 257 。這是由於地形太大,會形成大量頂點數據,給你的內存帶寬形成必定的影響,在目前的 ios 設備中,內存帶寬是很是有限的,須要儘可能節省。同時,若是用 Unity 自帶的地形,必定也要使用 Occlusion Culling ,由於 Unity 的刷地形工具雖然方便,但倒是 framekiller ,刷過以後,你會發現 drawcall 增長的很是多。
混合紋理數量
不要超過 4 。地形的混合操做是很耗時的,應該儘可能避免。能合併的紋理儘可能合併。
4、 紋理
紋理格式
建議 png tga 。不用轉成 ios 硬件支持的 PVRTC 格式,由於 Unity 在發佈時會幫你自動轉的。
紋理尺寸
長寬小於 1024 。同時應該儘量地小,夠用就好,以保證紋理對內存帶寬的影響達到最小。
支持 Mipmap
建議生成 Mipmap 。雖然這種作法會增長一些應用程序的大小,但在遊戲運行時,系統會根據需求應用 Mipmap 來渲染,從而減小內存帶寬。
檢查 Alpha
若是紋理的 alpha 通道均爲 1 ,則用 RGB 24 位紋理來代替 RGBA 32 位紋理。(聽說 Unity 內部會進行自動檢測)
5、 光源
光源「 Important 」個數
建議 1 個,通常爲方向光。「 Important 」個數應該越小越少。個數越多, drawcall 越多。
Pixel Light 數目
1-2 個。
6、 粒子特效
屏幕上的最大粒子數
建議小於 200 個粒子。
每一個粒子發射器發射的最大粒子數
建議不超過 50 個。
粒子大小
若是能夠的話,粒子的 size 應該儘量地小。由於 Unity 的粒子系統的 shader 不管是 alpha test 仍是 alpha blending 都是一筆不小的開銷。同時,對於很是小的粒子,建議粒子紋理去掉 alpha 通道。
儘可能不要開啓粒子的碰撞功能。
很是耗時。
7、 音頻
遊戲中播放時間較長的音樂(如背景音樂)
使用 .ogg .mp3 的壓縮格式。
較短音樂(如槍聲)
使用 .wav .aif 的未壓縮音頻格式。
8、 相機
裁剪平面
將遠平面設置成合適的距離。遠平面過大會將一些沒必要要的物體加入渲染,下降效率。
根據不一樣的物體設置不一樣的遠裁剪平面
Unity 提供了能夠根據不一樣的 layer 來設置不一樣的 view distance ,因此咱們能夠實現將物體進行分層,大物體層設置的可視距離大些,而小物體層能夠設置地小些,另外,一些開銷比較大的實體(如粒子系統)能夠設置得更小些等等。
9、 碰撞
儘可能不用 MeshCollider
若是能夠的話,儘可能不用 MeshCollider ,以節省沒必要要的開銷。若是不能避免的話,儘可能用減小 Mesh 的面片數,或用較少面片的代理體來代替。
10、 其餘
Drawcall
儘量地減小 Drawcall 的數量。
iOS 設備上建議不超過 100
減小的方法主要有以下幾種: Frustum Culling Occlusion Culling Texture Packing
Frustum Culling Unity 內建的,咱們須要作的就是尋求一個合適的遠裁剪平面; Occlusion Culling ,遮擋剔除, Unity 內嵌了 Umbra ,一個很是好 OC 庫。但 Occlusion Culling 也並非放之四海而皆準的,有時候進行 OC 反而比不進行還要慢,建議在 OC 以前先肯定本身的場景是否適合利用 OC 來優化;
Texture Packing ,或者叫 Texture Atlasing ,是將同種 shader 的紋理進行拼合,根據 Unity static batching 的特性來減小 draw call 。建議使用,但也有弊端,那就是必定要將場景中距離相近的實體紋理進行拼合,不然,拼合後極可能會增長每幀渲染所需的紋理大小,加大內存帶寬的負擔。
這也就是爲何會出現「 DrawCall 降了,渲染速度也變慢了」的緣由。

非運動物體儘可能打上 Static 標籤
Unity 在運行時會對 static 物體進行自動優化處理,因此應該儘量將非運行實體勾上 static 標籤。

場景中儘量地使用 prefab
儘量地使用 prefab 的實例化物體,以下降內存帶寬的負擔。檢查實體的 PrefabType ,儘可能將其變成 PrefabInstance ,而不是 ModelPrefabInstance html

相關文章
相關標籤/搜索