渲染大面積草地時,如何降低消耗?

1)在渲染大面積草地時,如何降低消耗
2)使用LoadFromMemory導致內存翻倍問題
3)對Android x86平臺的支持問題
4)OnGUI的堆內存分配問題


這是第200篇UWA技術知識分享的推送。今天我們繼續爲大家精選了若干和開發、優化相關的問題,建議閱讀時間10分鐘,認真讀完必有收穫。

UWA 問答社區:answer.uwa4d.com
UWA QQ羣2:793972859(原羣已滿員)

Rendering

Q:請問下大家,渲染大面積草地時,如何降低消耗呢?

A1:回答如下:
1.使用DrawMeshInstance;
2.上面這個API是不會進行視距剔除、視錐體剔除和遮擋剔除的。

下面有兩種方案:
a.將草地按區域分組,用每組的中心點計算視距,依據距離切換網格LOD或剔除;還能用向量點乘簡單剔除在相機後方的草地(注意臨界問題)。
b.藉助CullingGroup。
CullingGroup.onStateChanged事件綁定,通過事件觸發調整傳入;DrawMeshInstanced的Matrix順序和渲染數量(但是DrawMeshInstanced只能指定渲染前幾個Matrix);
通過cullingGroup.SetBoundingSpheres實現視錐體剔除和遮擋剔除;
通過cullingGroup.SetBoundingDistances實現視距剔除和LOD。
這個方案最好也進行區域分組,不然CullingGroup的事件監聽佔用會比較高,在中端機上4000個監聽會佔約2ms的大小。

以後如果有對比兩種方案的性能,我再進行補充。

附:

  1. 《CullingGroup API的使用說明》
  2. 《Unity 3D研究院之Lightmap支持GPU Instancing》
  3. 《如何高效使用GPU Instancing技術來進行草叢渲染》
  4. 升級Unity 2018,DrawMeshInstanced不生效的問題 

感謝題主李先生@UWA問答社區提供了回答

A2:使用Indirect模式的Instancing,配合Compute Shader實現視錐剔除和遮擋剔除。

感謝鄒春毅@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e919a528cabe84a011afcde


AssetBundle

Q:UWA的幾篇文章中都有說到儘量不要用AssetBundle.LoadFromMemroy接口,因爲這個接口會使得內存的佔用翻倍,但是我用Unity 2017.4.5f1進行測試後,發現AssetBundle.LoadFromMemroy和AssetBundle.LoadFromFile幾乎是沒有差別的,因爲文章中也沒有關於體積具體的版本信息。所以我想問是之前的Unity 4.x或者Unity 5.x版本纔有這個問題?還是說測試用例是有要求的呢?

另外,我是在PC上進行測試的,打包出exe,直接用任務管理器查看內存佔用情況,發現並沒有區別。

A1:應該是在C++裏面直接申請一塊內存用來解壓,Mono佔用不會變但是PSS會增大,內存峯值也會變高,使用adb shell dumpsys meminfo packageName來查看PSS。

如果目標平臺是PC,那就說明內存策略可能是分配後立即歸還給操作系統了。如果PC不是目標平臺,那麼看內存就沒有很大的意義。
感謝張迪@UWA問答社區提供了回答

A2:LoadFromMemroy輸入的byte數組用的是Mono堆內存,哪怕這個內存有釋放,但Mono堆內存總量是隻升不降的,在加載資源的過程中,一旦Mono觸發GC後仍內存不夠,很可能需要申請新的Mono內存,這會導致Mono內存持續升高。

而且用LoadFromMemroy沒有必要性,用這個接口哪怕內存不是問題,也會在加載資源時明顯比LoadFromFile慢不少,而且真的想要逆向AssetBundle資源還是很容易的。退一步說,非要加密建議使用LoadFromStream,然後自己去實現Stream解密。
感謝loy_liu@UWA問答社區提供了回答

A3: 我之前的測試有問題,現在更正一下:LoadFromMemroy即使在PC平臺也不如LoadFromFile接口。

經測試,PC上LoadFromMemroy接口內存的佔用大概會高1/5左右,加載時間比LoadFromFile接口慢1/5左右,而且如loy_liu所說,LoadFromMemroy接口需要先讀取byte數組,會產生Mono內存的分配問題,而LoadFromFile不會。在Android平臺上,內存的對比非常誇張,我這邊測試的數據翻了接近3倍。

所以儘量不要使用LoadFromMemroy接口,我沒有去測試LoadFromStream接口的性能和內存,但據說和LoadFromFile差不多。
感謝題主fdy@UWA問答社區提供了回答

A4: Lzma的資源包LoadFromMemory會導致資源本身翻倍。L4z資源包類似於管理器,本身佔用內存很小,翻倍也沒關係,而內存流本身也是用完就能扔。

感謝歐月鬆@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e8ed8c6cd6a9b49fb4a46a3


Build

Q:目前項目發佈後大於100MB,檢查發現是libil2cpp.so較大,大概大於60MB,而且同時支持了ARMv7、ARM64、x86,相當於x3的大小。所以想問一問大家,目前x86架構的機型大概佔比多少?需要繼續支持嗎?

 

A1: 沒必要,我建議去掉。
感謝loy_liu@UWA問答社區提供了回答

A2: 大多數模擬器都是X86,可以考慮下。
感謝歐月鬆@UWA問答社區提供了回答

A3: 需要支持,否則模擬器會很卡。

感謝Fly@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e9019ec8cabe84a011afc71


Memory

Q:在PC上運行遊戲,用Profile工具檢測的時候,發現GUIUtility.BeginGUI內存泄漏,每次調用產生0.8KB的內存消耗,每幀調用4次,就是3.2KB。請問這是什麼原因引起的呢?

 

A:OnGUI必然有GC Alloc,即使是空函數。你可以拿宏括起來,用來做Profiling的包不要編譯進去。

感謝littlesome@UWA問答社區提供了回答,歡迎大家轉至社區交流:
https://answer.uwa4d.com/question/5e86ec0dacb49302349a1141


今天的分享就到這裏。當然,生有涯而知無涯。在漫漫的開發週期中,您看到的這些問題也許都只是冰山一角,我們早已在UWA問答網站上準備了更多的技術話題等你一起來探索和分享。歡迎熱愛進步的你加入,也許你的方法恰能解別人的燃眉之急;而他山之“石”,也能攻你之“玉”。

官網:www.uwa4d.com
官方技術博客:blog.uwa4d.com
官方問答社區:answer.uwa4d.com
UWA學堂:edu.uwa4d.com
官方技術QQ羣:793972859(原羣已滿員)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章