Unity 性能优化 学习
1:unity 游戲安裝包大,運行游戲卡
Unity為什么可以跨平臺 因為它內置了mono虛擬機(跨平臺) 程序要先在虛擬機運行虛擬機再和操作系統交互 ??所以包體大運行卡 但是不是一定的原因 (如果沒有虛擬機直接游戲運行在操作系統就會快很多)
2:Draw Call 越大性能消耗越大 ?Gpu 相關
1:Draw Call 是Cpu對圖形繪制接口的調用,Cpu通過調用圖形庫(directx/opengl)接口,命令Gpu進行渲染操作
2:DrawCall真正的造成性能問題的是cpu 而不是Gpu 是切換渲染狀態導致
3:Cpu和Gpu是如何進行工作和交互的 首先采用渲染流水線 cpu和gpu并行工作,獨而不相互依賴,這是通過命令緩沖去來實現的 ?命令緩沖區維護一個命令隊列,cpu向其中發送命令,gpu從中提取命令并執行,命令有多種,DrawCall只是其中的一種,其他命令還有改變渲染狀態,設置渲染數據流等。這種方式就類似于游戲開發的網絡通信:維持一個消息隊列,網絡線程接收解析消息并將之添加到消息隊列,游戲主線程更新時從中取出消息并做派發處理。
4:DrawCall是如何影響性能的 每一次繪制Cpu都要調用DrawCall 而在調用Dw前cpu還要進行很多準備工作:檢測渲染狀態,提交渲染所需要的數據,提交渲染所需要的狀態,但是GPu本身有很強大的計算能力可以很快就處理完渲染任務當Dw過多,cpu就會很多額外開銷用于準備工作,cpu本身負載,而這個時候GPU可能閑置了 例如:拷貝1000個總大小1M的文件和單個大小為1M的文件,明顯拷貝1000個文件要慢很多,DrawCall調用和這個很類似。
5:Dw優化減少Dw ???Dw導致的性能問題是應為dw過多因此要減少dw優化游戲 ?首先批處理(batching) dw過多會造成cpu性能瓶頸:大量時間消耗在dw準備工作上 優化方向:盡量把小的dw合并到一個大的dw中這個就是 批處理的思想
3:合并批處理的注意事項?
1:合并的網格會在一次渲染任務中進行繪制,他們的渲染數據,渲染狀態和shader都是一樣的,因此合并的條件至少是:同材質,同貼圖,同shader.最好網格頂點格式也一致。
2:盡量避免使用大量小的網格,當確實需要時,考慮是否要合并
4:避免使用過多材質,盡量共享材質
5:網格合并的頂點數量有上限(unity 中好像是65535)
6:合并本身有消耗,因此盡量在編輯器下進行合并
確實需要運行合并的,將靜態的物體和動態的物體分開合并一次就可以,動態的只要物體發生變換就要重新合并
4:Unity Profiler 性能分析工具
Unity Statistisc Game窗口統計面板 ?Statistics窗口,全稱叫做?Rendering Statistics Window,即渲染統計窗口(或渲染數據統計窗口),窗口中羅列出關于聲音、圖像、網絡狀況等多種統計信息
FPS 每秒幀數 處理渲染所花費的時間 時間越小幀數越大越流暢 ?30幀人眼看不出來卡
CPU 計算每幀消耗的時間 越低越好
Render Thead 渲染線程 Gpu渲染圖像需要的時間 GPU顯卡性能決定 越低越好
Batches 批處理 和DrawCall有關 以DrawCall作為標準 ?unity內置的Dw批處理技術
Verts 頂點個數 攝像機視野(field of view)內渲染的頂點總數
tris ??三角面個數視野內 攝像機視野(field of view)內渲染的的三角面總數量
SetPass Call Shader里面很多 pass方法執行了多少個pass方法
5:Unity在 Player Setting 里的兩個功能選項 Static Batching 與 Dynamic Batching。功能描述如下:
Static Batching 是將標明為 Static 的靜態物件,如果在使用相同材質球的條件下,Unity 會自動幫你把這兩個物件合并成一個 Batch,送往 GPU 來處理。這功能對效能上非常的有幫助,所以是需要付費才有的。
Dynamic Batching 是在物件小于300面的條件下(不論物件是否為靜態或動態),在使用相同材質球下,Unity就會自動幫你合合并成一個 Batch 送往 GPU 來處理。
盡量不要修改Batches里物體的Scale,因為這樣會生成新的Batch
為了提升GPU的渲染效率,應當盡可能的在一個物體上使用較少的材質,減少Batches過多的開銷
對于場景中不會運動的物體,考慮設置Static屬性,Static聲明的物體會自動進行內部批處理優化
6:Unity資源優化
Mesh ?
動態模型:面片數< 3000 人物 怪物
材質數 < 3 ??
骨骼數 < 50
靜態模型 頂點數 < 500 場景等 ??
Audio
長時間的音樂(背景音樂) 壓縮格式mp3 ?減少安裝包大小 Compressed In Memory
短時間音樂 (音效) 非壓縮格式 wav ???Decompress On Load
有三種方式 Load Type
Decompress On Load
在硬盤上壓縮這個文件并在第一次加載到內存的時候解壓 試用于較小的壓縮聲音,避免即時解壓的性能開銷 ?用于音效小文件
Compressed In Memory
保持聲音在內存中是壓縮的并在播放時解壓縮 會有更多的cpu開銷,但可以提高加載速度并減少內存消耗?適用于大文件
Streaming 選項
直接從磁盤流音頻數據。這只使用了原始聲音占內存大小的很小一部分。 該方法使用最少的內存和最多的CPU,它有個很明顯的缺點就是不能被引用超過一次。試著讓 Audio?Clip產生多個副本的時候會每個都產生數據緩沖區,如果非要這么做會產生大量的內存和cpu消耗。因此這個選擇最好是給單實例的Audio Clip,如背景和環境音效。對于手游而言不要優先考慮使用這種方式。
其他一些加載設置
在場景中把一 個Audio Clip賦值給Audio Source組件,這個音頻文件將在場景初始化的時候加載到內存中。但是如果它啟用了,加載Audio Clip就變成了一個后臺任務它將推遲到場景初始化完成后再加載,換句話說就是在游戲開始后開始加載。 通過啟用這個選擇我們可以提高場景的啟動速度,但Play聲音的時候它還在后臺加載的話播放將推遲到加載完成,我們可以使用AudioClip對象的loadState 屬性來檢查是否加載完成以保證聲音在不會在一個不恰當的時間播放。
Preload?Audio?Data?默認是啟用的,它表示Unity自動在場景初始化時加載文件。禁用此選項將推遲加載直到 AudioSource的?Play() 或 PlayOneShot() 方法執行的時候。從硬盤加載聲音文件,然后解壓,再push到內存里然后再播放,這么一系列的動作 可能 會導致 CPU的峰值。
由于播放延遲和性能消耗,不建議在播放的瞬間加載。我們應該控制加載在播放之前的某些方便的時間使用AudioClip對象的LoadAudioData()方法加載。我們也可以用AudioClip對象的UnloadAudioData()方法手動控制聲音文件的內存釋放。
因為每個Audio?Source的播放都會消耗一定量的cpu,所以我們可以控制場景中?Audio?Source的數量來節省cpu。
減少AudioClip引用
https://blog.csdn.net/u012565990/article/details/51794486
Texture
貼圖長寬 ?< 1024 必須為2的冪次方 ??unity 最大貼圖支持 2048
本質上來講它是一個大的顏色數組告訴程序每個像素是什么顏色。
而Sprite是一個2d網格,一個平對著當前攝像機的quad,我習慣讀作精靈。
在Texture Type為Texture模式下Unity只給我們看到四個格式選項Compressed,?16-bit,True Color和Crunched
Crunched格式,這個格式壓縮需要很長時間,但在運行時減壓是非常快。???在新版本的Unity中加入了這個選擇可以看到它被壓縮成PVRTC格式,推薦在開發手機應用程序時使用 PVRTC 紋理
當使用 PVRTC 時與標準JPEG或PNG圖像相比有可能有些圖像質量的下降
不建議導入非正方形或者非2的次冪的紋理到我們的應用程序,因為GPU往往需要把紋理是變成正方形和2的次冪導致不必要的處理畸形的紋理尺 寸工作量。如果紋理不是2的次冪,Unity會scale、pad紋理,以使得達到2的次冪,這樣會花費更多內存,讓加載更慢,所以建議是避免導入非正方形和2的次冪的紋理。
Mip Maps
通過啟用?Generate Mip Maps???它會自動產生不同分辨率的多張相同紋理。在運行的時候,GPU根據在透視投影下出現的面積選擇適當的Mip Map(這是一種叫做 texel-to-pixel?ratio的技術 )
啟用Mip Maps還會讓最后生成的紋理文件增大33%左右
以下時候應該禁用這個選項:
1:在2d游戲中的幾乎所有的紋理(2d游戲正交投影不存在近大遠小)
2:UI界面
3:Mesh貼圖,Sprites,Particle Effects,因為他們總是在攝像機差不多的距離渲染不會有很明顯的距離差
4:打包圖集
Shader
盡量減少復雜數學運算 減少discard 操作 ?耗時的操作
7:模型優化 ??美術制作方面
1:減少面數,定點數(高低中檔模型)
2:貼圖優化
3:貼圖合并成一個 材質也就是一個了 減少Dw調用
8:如何減少冗余資源和重復資源
9:資源的檢測與分析
分析 assetbundle 分析安裝包里面的冗余資源
https://www.uwa4d.com/#assetbundle??UWA 分析工具 第三方檢測工具
10:渲染優化
Cpu Gpu 分工
11:LOD 層級細節 ?在不同的距離顯示不同精細的模型 占用空間
1:創建個空物體 添加LODGroup 組件 ?0精細 1一般 2粗略 ?culled 看不見不顯示
?
這個長度站的比例可以調節
在LOD2和LOD1可以修改貼圖的品質,Cast Shadow和 ReceiveShadow可以移除??(陰影)
12:Occlusion Culling - 遮擋剔除
只渲染在視野內的物體,視野外的不渲染 場景中很多的物體 如樹
1:選擇那些物體要進行遮擋剔除
2:選擇后要在 Occlusion 里面選擇 Object 點擊 Bake 烘焙
3:Visualization 里面選擇Cameras 選擇渲染攝像機(依據哪個Camera進行遮擋剔除的計算)
13:光照貼圖 LightMapping
在場景中的物體有很多點光源或者其他環境光源 光照光源計算是很消耗性能的,把這個光照的效果提前計算好,生成一張光照貼圖,這樣游戲運行時就不用再計算了
選擇window - Lighting ??點擊GenreateLighting
要把需要烘焙的光源設置為baked
工程里面會多一個這樣的貼圖
14:Mesh合并 ?
可以在3dMax 瑪雅合并 也可以代碼合并 ?MeshFilter 模型顯示的網格 ?MeshRender 模型顯示的渲染材質 shader
1 shader相同的物體才可以合并
?2 要合并的物體必須處于一定的范圍內我們在合并之前會將場景劃分為多個正方體,每個正方體內的物體才能互相合并在一起,以此避免合并出來物體的mesh分散的情況。
3 物體的光照貼圖?lightMapindex 屬性相同
//寫一個Editor 工具
void GetMesh(Transform ts) {//獲取自身和所有子物體中所有MeshFilter組件MeshFilter[] meshFilters = ts.GetComponentsInChildren<MeshFilter>(); //新建CombineInstance數組 CombineInstance[] combine = new CombineInstance[meshFilters.Length]; //獲取自身和所有子物體中所有MeshRenderer組件 MeshRenderer[] Renderer = ts.GetComponentsInChildren<MeshRenderer>(); //新建材質球數組Material[] mats = new Material[Renderer.Length]; for (int i = 0; i < meshFilters.Length; i++){//獲取材質球列表mats[i] = Renderer[i].sharedMaterial; combine[i].mesh = meshFilters[i].sharedMesh;//矩陣(Matrix)自身空間坐標的點轉換成世界空間坐標的點 //combines[i].transform = meshFilters[i].transform.localToWorldMatrix;//變換矩陣的問題,要保持相對位置不變,要轉換為父節點的本地坐標,combines[i].transform = ts.worldToLocalMatrix * meshFilters[i].transform.localToWorldMatrix; //除了根物體,其他物體統統銷毀if (meshFilters[i].gameObject.name != gameObject.name) {Destroy(meshFilters[i].gameObject);}}ts.GetComponent<MeshFilter>().mesh = new Mesh(); /*為mesh.CombineMeshes添加一個 false 參數,表示并不是合并為一個網格,而是一個子網格列表,可以讓擁有多個材質球,如果要合并的網格用的是同一材質,false改為true,同時將上面的獲取Material的代碼去掉*/ts.GetComponent<MeshFilter>().mesh.CombineMeshes(combine, false);//為合并后的GameObject指定材質球數組ts.GetComponent<MeshRenderer>().sharedMaterials = mats; }另外盡量保證根物體的縮放是1:1:1,不然就會發現合并完的模型完全變形了。
15:CPU優化
資源對象池優化
1: 對象池類, (擴展可以分類型獲得不同的對象池)
2:對象池大小 (也可以初始化先創建好對象)
3:對象池保存的數據(List,字典等格式)
4: 添加對象方法(清空對象屬性方法)
5: 減少對象方法(或者是取出一個對象的方法)
6:初始化或者重置對象屬性方法
代碼編譯優化
放到pluging Editor 文件夾下等
?
總結
以上是生活随笔為你收集整理的Unity 性能优化 学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 聘用计算机人员申请书范文,岗位聘用的申请
- 下一篇: qldump 备份所有表_mysqldu