Unity查看當前內存使用情況(針對移動端開發)


 Unity3D為我們提供了一個強大的性能分析工具Profiler。今天我們就使用Profiler來詳細分析一下官方例子AngryBots的內存使用信息數據。

 首先打開Profiler選擇Memory選項,在游戲運行的某一幀查看Detailed選項數據(Simple模式的數據很直觀,可以知道內存大體被哪部分占用了),如下圖所示:

選中后,unity會自動獲取這一幀的內存占用數據項,主要分為:Other、Assets、BuiltinResources、Scene Memory、NotSaved這五大部分,下面我們就來一一分析。

  • Other

記錄數據項很多,篇幅時間有限,我們就專挑占用大小排行榜靠前的幾項來詳細分析吧。

  • 統可執行程序和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:重點優化對象,有以下幾點可以優化:

  1. 許多貼圖采用的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。
  2. 當加載一個新的Prefab或貼圖,不及時回收,它就會永駐在內存中,就算切換場景也不會銷毀。應該確定物體不再使用或長時間不使用就先把物體制空(null),然后調用Resources.UnloadUnusedAssets(),才能真正釋放內存。
  3. 有大量空白的圖集貼圖,可以用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的堆內存.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM