拖公司的福,有幸去了一趟北京參加了一場Unity3D的交流盛宴,在爲期兩天的時間內,不只有着技術上收穫,也有心靈上的震撼。如今先來講說技術方面的一些比較重要的知識,可是會跳過Unity3D後續版本的一些新功能介紹,好比新的GUI、動畫系統的增強、以及新的AssetBundle打包工具。由於等以後版本出來後,天然會有更加詳細的文檔以及說明出來。程序員
項目開發、管理和發佈策略
四大準則
- 準則一:美術資源量對於程序發佈包大小、性能優化、內存佔用量的影響,每每超過其餘各類因素
- 技術美術和關卡設計師對於遊戲性能承擔着很是重要的責任
- 程序員每每沒法補救因爲濫用美術資源而形成的性能問題
- 準則二:項目團隊應該經過編寫工具來保證美術資源的合法性
- 美術規範文檔沒法在實際上保證美術資源的合法性
- 程序員應該經過Unity編輯器擴展技術,爲美術師實現完整的美術資源合法性檢查工具
- 準則三:對渲染效率和內存佔用的優化應該在項目實施過程當中反覆進行
- 針對CPU端/遊戲邏輯的優化每每可以比針過GPU端/Shader的優化取得更大的做用
- GPU/Shader的性能優化應該放在最後進行
- 善用Unity Profilers (這點很是重要,後面會有對這個功能的詳細講解)
- 準則四:從反向工程的角度理解項目開發,以最終須要達到的目的來決定程序的架構設計以及關鍵技術的方案選擇
- 是否須要進行代碼的增量更新
- 是否須要嚴格控制程序發佈包的大小
- 是否須要支持低端移動設備等等
Mipmaps
-
凡是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
老的AssetBundle打包的時候有比較多的弊端,依賴打包的時候很麻煩。一個包改變了,相關聯的包都要從新打一次包,這個過程會嚴重的影響開發效率。這個問題在Unity 5.0會獲得解決架構
AssetBundle的效率比Resources效率要低。這是沒辦法的事編輯器
Profiler 性能分析器
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以上內存分配的選項
- GameObject.GetComponet()會引發GC的分配
-
Time
記錄了遊戲運行時的每幀cpu打敗。固然是越小越好,若是佔用過大那就找緣由吧。
-
CPU Usage
- WaitForTargetFPS
- vSync功能所致或者幀數限制
- Overhead
- 全部沒法統計的時間總和,理論值應該爲0.
- Physics.Simulate
- 物理模擬佔用的CPU
- Camera.Render
- 相機渲染準備工做的CPU佔用量
- RenderTexture.SetActive 設置RenderTexture操做(和相機數一致)
- 比對當前幀與前一幀的ColorSurface和DepthSurface
- 若是一致則不生成新的RT, 不然則生成新的RT,並設置與之相對應的Viewport和空間轉換矩陣
- GUI.Repaint
- GUI的重繪,使用的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
在資源加載時會用到,對每種資源進行處理
- WaitForTargetFPS
-
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加載時容易出現該問題
- Shader.CreateGPUProgram
-
StackTraceUtility.PostprocessStackTrace() StackTraceUtility.ExtractStackTrace()
Debug.Log()調試信息形成,這是一個很耗時間的操做。發佈的時候儘可能去掉
-
GarbageCollectAssetsProfile
引擎在執行UnloadUnusedAssets操做
-
總結
授人以魚,不如授人以漁。技術的進步是無止境的,大部分的時候都須要咱們本身去解決問題,只有方法纔是真正的解決問題之道。
-
善用、活用Profiler!
- 常用Profiler爲項目來進行體驗
- 經過Profiler.BeginSample和Profiler.EndSample來自定義檢查範圍
-
關注CPU & Memory Profiler
- GC Alloc、 Time、 Assets、WebStream…
-