您當前的位置:首頁 > 舞蹈

【程式】Unity 效能 Review

作者:由 Mack 發表于 舞蹈時間:2017-11-23

年初的一次最佳化筆記,第一篇。每個版本一週,每個版本一篇已經6,7篇了。過早的最佳化可能並不是最好的,但是每個版本每個月都要上線測試。始終覺得對於實時多人競技遊戲來說,流暢的重要性超過畫面。

使用Unity的Profile先簡單分析

角色更新過高,後面更詳細的分析。

【程式】Unity 效能 Review

螢幕邊緣圖示和Wifi過高。最佳化方案:頻繁設定UI文字和貼了可以最佳化。

【程式】Unity 效能 Review

放技能開銷非常高,每個子彈有獨立彈道邏輯,技能釋放頻率比價高。最佳化方案:類物件使用記憶體池,delegate最佳化減少gc,更完善的預載入機制,邏輯最佳化等等。CMT的timer使用記憶體池。

【程式】Unity 效能 Review

【程式】Unity 效能 Review

部分非技能的CMT沒有預載入。

【程式】Unity 效能 Review

召喚物沒有預載入。

【程式】Unity 效能 Review

部分道具有些沒有預載入。

【程式】Unity 效能 Review

訊息處理非常卡。解決方案:使用類物件記憶體池,最佳化序列化方式不使用protobuff的。

【程式】Unity 效能 Review

幀操作增減人會卡。解決方案:推測玩家行為預載入。

【程式】Unity 效能 Review

飛行道具開銷很高,特別是Deactive上。解決方案:可見性使用layer,使用記憶體池

【程式】Unity 效能 Review

地圖指令碼開銷較高。

【程式】Unity 效能 Review

Camera。main直接呼叫開銷較高。解決方案:因為Unity會遍歷所有的Camera,是一個線性時間。在Update中呼叫的話,快取一下main

camera。

使用Unity的FrameDebugger簡單分析

俯視角開啟了天空球渲染,其實沒必要

【程式】Unity 效能 Review

使用Unity MemoryProfiler分析記憶體佔用和記憶體洩漏

透過memoryprofile抓幀分析,記憶體佔用不高,但是RenderTexture佔用非常高63。5M

大廳場景RenderTexture 63。5m。解決方案:因為使用了景深,擾動,螢幕校色,實時陰影,等後期處理效果所致,我們根據玩家手機配置做了自適應和限定,並且再圖形配置選項允許玩家做一些調整。景深開銷非常高因此關閉了實時景深效果使用其他方法代替。

戰鬥場景Texture 33。7m Mesh 14。9m animationclip 3。7m Audiomanager 4。1M。解決方案:貼圖壓縮,使用shader減少換色貼圖,修正一些貼圖引用不釋放導致的記憶體洩漏。

LockstepMnanager。FixedUpdate函式 每幀分配10kb以上記憶體。解決方案:各種GC相關的最佳化。

SceneLoader。update函式(315 bytes) MainLoop。Update函式(202bytes), NetManager。update函式(186bs) CharacterActor。LateUpdate函式(392 bytes)皆為每幀都分配。GC的分配每幀超過200b就算大了。解決方案:各種記憶體最佳化,訊息使用記憶體池等等。

MainLoop。OnGUI函式每幀分配記憶體 300b。解決方案:刪掉空函式。

大廳場景Camera。Render cpu等待gnu渲染,造成時間幀率抖動 25ms-> 43ms 體現為Camera。Render self時間大幅變動 (最佳化方法 降低場景面數,拆分Gm_Cabin模型)

Loading貼圖存在偽記憶體洩漏,因為圖集和按鈕放在一起了被按鈕引用。

Unity技術支援提供了指令碼外掛可以分析程式碼中所有靜態的引用。發現是lua的LuaScriptMgr中會對一些貼圖有引用,需要注意使用Lua導致的記憶體問題。

使用XCode做詳盡的效能最佳化

XCode也可以做GPU的效能分析。編譯xcode工程需要Development版,啟動,GUP的最佳化點需要在Run的面板裡設定成metal否則有些堆疊看不到。點FPS,然後點相機Capture一幀,可以看到幀率,CPUGPU的佔比,渲染時每個函式的開銷。點Shader裡面的看更詳細堆疊,可以看到每個shader的每行程式碼的開銷佔比。

這個版本大廳很簡單但是非常非常卡,看到UI和景深開銷佔比比較高,UI佔了25,景深佔了30。看到UI費是取樣一張貼圖佔了50但是這張貼圖並不大,景深費是因為shader裡lerp了很多次導致開銷很高。在FrameDebugger裡可以看到UI最後渲染了一個全屏的面,可以看到每次渲染了佔用的時間比,這個面實際沒用。關閉了這個UI的全屏面,關了景深和後處理,基本就沒開銷了,連UI的渲染也只有2ms了因為景深把匯流排頻寬給佔滿了,其中最費的還是景深效果。

【程式】Unity 效能 Review

渲染執行緒開銷也較高

【程式】Unity 效能 Review

版本機出的版本在XCode中會報錯APPLE MACH-O Linker Error,無法做效能分析。解決方法:改成il2cpp了。

修復字串拼接的量級,使用StringBuilder等。

OnGUI,FixedUpdate,Update等空函式也會有gc開銷,因為會產生從C++到C#層呼叫的開銷。最好都去掉。

FMOD音效模組開銷過高。我們沒使用官方的FMOD使用了FMODStudio,測試版資源為了效果和開發方便使用了一些事件內的效果器。最佳化後音效佔用10-15%。

【程式】Unity 效能 Review

動畫開銷較高,使用了動作融合,動畫狀態機較複雜。解決方案:不可見的角色不更新動畫,一些頂點受骨骼影響數可以設定很小,小怪等簡單角色使用Animation,動畫的一些最佳化等。

【程式】Unity 效能 Review

UI,粒子,動作開銷較高,並且多執行緒開銷也高。

【程式】Unity 效能 Review

可以看到每個模組開銷比較平均,已經做了很多優化了沒有明顯瓶頸,只能一個模組一個模組的摳了

【程式】Unity 效能 Review

其他一些測試以及和Unity官方支援的問答:

Unity的物理比射線省,因為會最佳化做空間劃分,只計算較小範圍。Navmesh最最佳化。

迷霧和可以性檢測可見性預快取,預快取分塊載入,迷霧進行分塊劃分最佳化,分擔計算量到多幀執行等等

Resource目錄資源多會導致Unity進遊戲時間特別長,因為會把Resource下所有資源做一次檢索,導致啟動慢。建議使用Assertbundle,也支援壓縮。另外提升進入遊戲速度的就是,第一個場景足夠簡單足夠小。解決方案:開發了熱更的資源管理,每個資源有一個唯一ID,可以存在Resource下也可以存在Assertbundle中。

Assetbundle的新演算法是按Chunk載入,不會把整個Assertbundle都載入進來但是壓縮比小,壓縮的時候要選擇ChunkBase。如果bundle載入好之後資源的引用時放在bundle上,如果a介面開啟bundle包讀取貼圖,a介面關閉則貼圖會釋放,如果a沒關閉,b介面讀取貼圖b介面會對應到同一張貼圖上。

建議bundle放在StreamingAssets目錄下。

Profile分析建議:Overhead,是Unity沒統計到的時間,用總計時間減去剩餘的時間,一般包括C++到C#層的呼叫開銷,場景複雜度,垂直同步等。大廳因為Overhead卡是因為CPU在等GPU,建議用XCode看。

透過Profile。BeginSample自己插程式碼對懷疑的程式碼進行記憶體和效能除錯。

Unity5。3。5p8修改了Foreach裝箱拆箱導致的記憶體開銷。但是沒有修改mono的gc。實際測試可以用Foreach了。

部分Android裝置匯流排太爛導致GC會特別卡

OnGUI,FixedUpdate,Update等空函式也會有gc開銷,因為會產生從C++到C#層呼叫的開銷。最好都去掉

部分3G的Android裝置,實際可用記憶體可能只有500M。Unity啟動時最高能佔到80M,一般在40-50M

unload切場景自動調,gc也會自動調

編輯器下看到的資源引用計數不準確,得看真機。實際測試的時候老發現很多資源釋放不掉,但是到真機測試發現實際已經釋放掉了,因為編輯器模式會快取一些資源,所有的測試都應該以真機為準。

lua導致gc太多,沒有比較好的解決辦法,把lua的程式碼放到C# 層

IOS上如果限45幀對IOS來說就是限30幀,低於30幀才是真實幀率

CPU最佳化:ulua的計時器開銷很大。其中PreloadManager是Unity的各個模組的預載入。

GPU最佳化:Mask會很費。

標簽: 開銷  記憶體  最佳化  Unity  貼圖