拖公司的福,有幸去了一趟北京參加了一場Unity3D的交流盛宴,在為期兩天的時間内,不僅有着技術上收獲,也有心靈上的震撼。現在先來說說技術方面的一些比較重要的知識,但是會跳過Unity3D後續版本的一些新功能介紹,比如新的GUI、動畫系統的加強、以及新的AssetBundle打包工具。因為等之後版本出來後,自然會有更加詳細的文檔以及說明出來。
準則一:美術資源量對于程式釋出包大小、性能優化、記憶體占用量的影響,往往超過其他各種因素
技術美術和關卡設計師對于遊戲性能承擔着非常重要的責任
程式員往往無法補救由于濫用美術資源而造成的性能問題
準則二:項目團隊應該通過編寫工具來保證美術資源的合法性
美術規範文檔無法在實際上保證美術資源的合法性
程式員應該通過Unity編輯器擴充技術,為美術師實作完整的美術資源合法性檢查工具
準則三:對渲染效率和記憶體占用的優化應該在項目實施過程中反複進行
針對CPU端/遊戲邏輯的優化往往能夠比針過GPU端/Shader的優化取得更大的作用
GPU/Shader的性能優化應該放在最後進行
善用Unity Profilers (這點非常重要,後面會有對這個功能的詳細講解)
準則四:從反向工程的角度了解項目開發,以最終需要達到的目的來決定程式的架構設計以及關鍵技術的方案選擇
是否需要進行代碼的增量更新
是否需要嚴格控制程式釋出包的大小
是否需要支援低端移動裝置等等
凡是3D場景,都應該盡可能啟用MipMaps
耗費記憶體,提升CPU
為什麼進行分級
移動GPU之間的性能差距可能高達10倍以上
效率和效果之間永遠存在着沖突
怎麼分級
Resolution分辨率
Post-processing 後期特效
MSAA 反鋸齒
Anisotropy 異向紋理
Shaders
Fx/particles density, on/off 粒子發射器的數量、密度。單人和多人的不同處理
一個遊戲可以使用的記憶體容量簡單的可以了解為:可用記憶體為整個記憶體的%50。比如512M的内在可以使用256M。
控制貼圖大小
選擇合适的壓縮格式PVRTC,DXT,ATC,ETC
使用Prefabs
用好AssetBundles
編寫自己的ObjectPool和LoadManager
通過對象池來避免記憶體的頻繁操作,進而避免記憶體碎片影響到大記憶體塊的申請;切換場景時不釋放公共的UI資源
通過LoadManager,保證在同一時間段内公載入一個www對象,實作順序加載
老的AssetBundle打包的時候有比較多的弊端,依賴打包的時候很麻煩。一個包改變了,相關聯的包都要重新打一次包,這個過程會嚴重的影響開發效率。這個問題在Unity 5.0會得到解決
AssetBundle的效率比Resources效率要低。這是沒辦法的事
Unity3D提供了一個非常強大、非常易于使用的性能分析器,在平常的使用過程中或多或少都會碰到一些搞不明白的地方,這一次官方給了一個比較詳細的解答。一些簡單的功能就不在此介紹了,一看就懂。
GC Alloc
記錄了遊戲運作時代碼産生的堆記憶體配置設定,這是一個非常重要的參數,甚至比Time更加重要。ManagedHeap的增大,會加速GC回收的到過。如果這個參數有一個比較高的值或者出現在每一幀中,那麼就要引起重視。以下是一些不太引起注意的地方引起的GC配置設定:
GameObject.GetComponet()會引起GC的配置設定盡量緩存元件
Object.get_name()如果每一幀都需要比較,可以緩存名字
foreach循環每次foreach會産生一個enumerator
盡可能避免使用LINQ
部分功能無法在某些平台上使用
會配置設定大量GC Alloc
協程Coroutine開啟一個協程,至少配置設定373的記憶體
String連接配接
使用StringBuilder或String.Format來代替而不是用”+”來進行連接配接
關注原則:
檢測任何一次性記憶體配置設定大于2KB的選項
檢測每幀都具有20B以上記憶體配置設定的選項
Time
記錄了遊戲運作時的每幀cpu戰勝。當然是越小越好,如果占用過大那就找原因吧。
CPU Usage
WaitForTargetFPSvSync功能所緻或者幀數限制
Overhead所有無法統計的時間總和,理論值應該為0.
Physics.Simulate實體模拟占用的CPU
Camera.Render相機渲染準備工作的CPU占用量
RenderTexture.SetActive 設定RenderTexture操作(和相機數一緻)
比對目前幀與前一幀的ColorSurface和DepthSurface
如果一緻則不生成新的RT, 否則則生成新的RT,并設定與之相對應的Viewport和空間轉換矩陣
GUI.RepaintGUI的重繪,使用的Unity3D自帶的GUI,極度不推薦使用
Cleanup Unused Cached Data
清空無用的緩存資料,主要包括RenderBuffer的垃圾回收和TextRendering的垃圾回收
RenderTexture.GarbageCollectTemporary
存在于RenderBuffer的垃圾回收中,清楚臨時的FreeTexture
TextRendering.Cleanup
TextMesh的垃圾回收操作
Application.Integrate Assets in Background
周遊預加載的線程隊列并完成加載,同時,完成紋理的加載、Substance的Update等。主要是加載場景的時候會用到,多線程加載
AssetBundle.LoadAsyncIntegrate
多線程加載AssetBundle的資源
Loading.AwakeFromLoad
在資源加載時會用到,對每種資源進行處理
GPU Usage
Mesh.DrawVBO
GPU中關于Mesh的Vertex Buffer Object的渲染耗時
Shader.Parse
資源加入後引擎對Shader的解析過程
Shader.CreateGPUProgram
根據目前裝置支援的圖開庫資訊來建立GPU工程
Profiler需要時刻關注的參數
CPU—GC Alloc
CPU—Time
MemoryProfiler—Other
ManagedHeap.UsedSize
移動遊戲建議不超過20M
WebStream
通過WWW加載留下的東西,一般會比SerializedFile大得多。包括壓縮和解壓的東西
SerializedFile
通過WWW等方式加載本地的AssetBundle的留下的序列化檔案,看是否被解除安裝掉
MemoryProfiler—Assets檢視是否有重複的資源
Device.Present
GPU的Presentdevice确實非常耗時,一般出現在使用了非常複雜的Shader等;
GPU運作的非常快,而由于Vsync的原因,使得它需要等待較長時間;
同樣是VSync的原因,但其他線程非常耗時,是以導緻該項等待時間很長,比如過量的assetbundle加載時容易出現該問題
StackTraceUtility.PostprocessStackTrace() StackTraceUtility.ExtractStackTrace()
Debug.Log()調試資訊造成,這是一個很耗時間的操作。釋出的時候盡量去掉
GarbageCollectAssetsProfile
引擎在執行UnloadUnusedAssets操作
總結
授人以魚,不如授人以漁。技術的進步是無止境的,大部分的時候都需要我們自己去解決問題,隻有方法才是真正的解決問題之道。
善用、活用Profiler!
經常使用Profiler為項目來進行體驗
通過Profiler.BeginSample和Profiler.EndSample來自定義檢查範圍
關注CPU & Memory Profiler
GC Alloc、 Time、 Assets、WebStream…
Andriod版本無法連接配接Profiler調試
adb forward tcp:54999 localabstract:Unity-\
再次選擇AndriodProfiler([email protected]:54999)