轉載自:http://blog.csdn.net/yangyy753/article/details/47025205
Unity3D為我們提供了一個強大的性能分析工具Profiler。今天我們就使用Profiler來詳細分析一下官方例子AngryBots的記憶體使用資訊資料。
首先打開Profiler選擇Memory選項,在遊戲運作的某一幀檢視Detailed選項資料(Simple模式的資料很直覺,可以知道記憶體大體被哪部分占用了,網上也有很多相關介紹,我就不再啰嗦了),如下圖所示:
選中後,unity會自動擷取這一幀的記憶體占用資料項,主要分為:Other、Assets、BuiltinResources、Scene Memory、NotSaved這五大部分,下面我們就來一一分析。
- Other
記錄資料項很多,篇幅時間有限,我們就專挑占用大小排行榜靠前的幾項來詳細分析吧。
- System.ExecutableAndDlls:系統可執行程式和DLL,是隻讀的記憶體,用來執行所有的腳本和DLL引用。不同平台和不同硬體得到的值會不一樣,可以通過修改Player Setting的Stripping Level來調節大小。
Ricky:我試着修改了一下Stripping Level似乎沒什麼改變,感覺雖占用記憶體大但不會影響遊戲運作。我們暫時忽略它吧(- -)!
- GfxClientDevice:GFX(圖形加速\圖形加速器\顯示卡 (GraphicsForce Express))用戶端裝置。
Ricky:雖占用較大記憶體,但這也是必備項,沒辦法優化。繼續忽略吧(- -)!!
- ManagedHeap.UsedSize:托管堆使用大小。
Ricky:重點監控對象,不要讓它超過20MB,否則可能會有性能問題!
- ShaderLab:Unity自帶的着色器語言工具相關資源。
Ricky:這個東西大家都比較熟悉了,忽略它吧。
- SerializedFile:序列化檔案,把顯示中的Prefab、Atlas和metadata等資源加載進記憶體。
Ricky:重點監控對象,這裡就是你要監控的哪些預設在序列化中在記憶體中占用大小,根據需求進行優化。
- PersistentManager.Remapper:持久化資料重映射管理相關
Ricky:與持久化資料相關,比如AssetBundle之類的。注意監控相關的檔案。
- ManagedHeap.ReservedUnusedSize:托管堆預留不使用記憶體大小,隻由Mono使用。
Ricky:無法優化。
- Assets
- Texture2D: 2D貼圖及紋理。
Ricky:重點優化對象,有以下幾點可以優化:
- 許多貼圖采用的Format格式是ARGB 32 bit是以保真度很高但占用的記憶體也很大。在不失真的前提下,适當壓縮貼圖,使用ARGB 16 bit就會減少一倍,如果繼續Android采用RGBA Compressed ETC2 8 bits(iOS采用RGBA Compressed PVRTC 4 bits),又可以再減少一倍。把不需要透貼但有alpha通道的貼圖,全都轉換格式Android:RGB Compressed ETC 4 bits,iOS:RGB Compressed PVRTC 4 bits。
- 當加載一個新的Prefab或貼圖,不及時回收,它就會永駐在記憶體中,就算切換場景也不會銷毀。應該确定物體不再使用或長時間不使用就先把物體制空(null),然後調用Resources.UnloadUnusedAssets(),才能真正釋放記憶體。
- 有大量空白的圖集貼圖,可以用TexturePacker等工具進行優化或考慮合并到其他圖集中。
- AudioManager:音頻管理器
Ricky:随着音頻檔案的增多而增大。
- AudioClip:音效及聲音檔案
Ricky:重點優化對象,播放時長較長的音樂檔案需要進行壓縮成.mp3或.ogg格式,時長較短的音效檔案可以使用.wav 或.aiff格式。
- Cubemap:立方圖紋理
Ricky:這個一般在天空盒中比較常見,我也不知道如何優化這個。。。
- Mesh:模型網格
Ricky:主要檢查是否有重複的資源,還有盡量減少點面數。
- Scene Memory
- Mesh:場景中使用的網格模型
Ricky:注意網格模型的點面數,能合并的mesh盡量合并。
- Builtin Resources
Ricky:這些都是Unity的一些内部資源,對于項目記憶體沒有什麼分析價值,是以我就暫時不對其進行分析了。
- Profiler記憶體重點關注優化項目
1)ManagedHeap.UsedSize: 移動遊戲建議不要超過20MB.
2)SerializedFile: 通過異步加載(LoadFromCache、WWW等)的時候留下的序列化檔案,可監視是否被解除安裝.
3)WebStream: 通過異步WWW下載下傳的資源檔案在記憶體中的解壓版本,比SerializedFile大幾倍或幾十倍,不過我們現在項目中展示沒有。
4)Texture2D: 重點檢查是否有重複資源和超大Memory是否需要壓縮等.
5)AnimationClip: 重點檢查是否有重複資源.
6)Mesh: 重點檢查是否有重複資源.
- 項目中可能遇到的問題
1.Device.Present:
1)GPU的presentdevice确實非常耗時,一般出現在使用了非常複雜的shader.
2)GPU運作的非常快,而由于Vsync的原因,使得它需要等待較長的時間.
3)同樣是Vsync的原因,但其他線程非常耗時,是以導緻該等待時間很長,比如:過量AssetBundle加載時容易出現該問題.
4)Shader.CreateGPUProgram:Shader在runtime階段(非預加載)會出現卡頓(華為K3V2晶片).
5)StackTraceUtility.PostprocessStacktrace()和StackTraceUtility.ExtractStackTrace(): 一般是由Debug.Log或類似API造成,遊戲釋出後需将Debug API進行屏蔽。
2.Overhead:
1)一般情況為Vsync所緻.
2)通常出現在Android裝置上.
3.GC.Collect:
原因:
1)代碼配置設定記憶體過量(惡性的)
2)一定時間間隔由系統調用(良性的).
占用時間:
1)與現有Garbage size相關
2)與剩餘記憶體使用顆粒相關(比如場景物件過多,使用率低的情況下,GC釋放後需要做記憶體重排)
4.GarbageCollectAssetsProfile:
1)引擎在執行UnloadUnusedAssets操作(該操作是比較耗時的,建議在切場景的時候進行)。
2)盡可能地避免使用Unity内建GUI,避免GUI.Repaint過渡GCAllow.
3)if(other.tag == a.tag)改為other.CompareTag(a.tag).因為other.tag為産生180B的GC Allow.
4)少用foreach,因為每次foreach為産生一個enumerator(約16B的記憶體配置設定),盡量改為for.
5)Lambda表達式,使用不當會産生記憶體洩漏.
5.盡量少用LINQ:
1)部分功能無法在某些平台使用.
2)會配置設定大量GC Allow.
6.控制StartCoroutine的次數:
1)開啟一個Coroutine(協程),至少配置設定37B的記憶體.
2)Coroutine類的執行個體 -> 21B.
3)Enumerator -> 16B.
7.使用StringBuilder替代字元串直接連接配接.
8.緩存元件:
1)每次GetComponent均會配置設定一定的GC Allow.
2)每次Object.name都會配置設定39B的堆記憶體.
Ricky Yang個人原創,版權所有,轉載注明,謝謝。http://blog.csdn.net/yangyy753