https://zhuanlan.zhihu.com/p/26030252
1.渲染
利用reflect probe代替反射、折射,盡量不用RTT、GrabPass、RenderWithShader、CommandBuffer.Blit (BuiltinRenderTextureType.CurrentActive...) 建立統一後處理架構(bloom、hdr、DOF等)代替多後處理,可以共用模糊函數,減少多次blit;另外要注意RTT的尺寸。 空氣折射、熱浪扭曲等使用GrabPass不是所有硬體都支援,改為RTT或者後處理來最佳化。 建立統一shader材質代替單一shader,充分利用shader_feature、multi_compile,並將宏開關顯示於介面。 映像混合代替多通道紋理,陰影投射、陰影接收、MetaPass、forwardadd 等pass不需要時要剔除。 少用alpha test、discard、clip、Alpha Converage等,因為會影響Early-Z Culling、HSR的最佳化。 避免Alpha Blend穿透問題(權重混合、深度剝離等透明排序方法代價太大了)。 光照貼圖代替動態陰影、盡量不用即時光;陰影貼圖、環境貼圖用16位代替32位;利用projector+rtt或者光圈代替即時陰影。 將環境參數(風、雨、太陽)等shader全域參數統一管理。 非主角可以用matcap代替pbr、無金屬不一定要用pbr,仔細選擇物理渲染所用的FDG(F:schlick、cook-torrance、lerp、要求不高用4次方,D:blinn-phong、beckmann、GGX、GGX Anisotropic,G:neumann、cook-torrance、Kelemen、SmithGGX;standard shader要注意選擇BRDF1-BRDF3),渲染要求不高時不用GGX;可以用LH來最佳化GGX。 用fixed、half代替float,建立shader統一類型(fixed效率是float的4倍,half是float的2倍),小心選擇shader變數的修飾(uniform、static、全域),選擇Mobile或Unlit目錄下shader 使用高低配渲染,記憶體足夠時可以考慮開啟mipmap 使用surface shader注意關掉不用的功能,比如:noshadow、noambient、novertexlights、nolightmap、nodynlightmap、nodirlightmap、nofog、nometa、noforwardadd等 standard shader的變體太多(3萬多),導致編譯時間較長,記憶體佔用也很驚人(接近1G),如果使用要關掉沒用的shader_feature,比如:_PARALLAXMAP、SHADOWS_SOFT、DIRLIGHTMAP_COMBINED DIRLIGHTMAP_SEPARATE、_DETAIL_MULX2、_ALPHAPREMULTIPLY_ON;另外要去掉多餘的pass shaderforge、Amplify Shader Editor產生的shader有多餘代碼要程式專門最佳化,Amplify Shader Editor功能更強大一些,而且開源,建議學習。 不要用unity內建terrian,因為即使只用3張splat圖,shader也是對應4個的,建議T4M或者轉為mesh。 模型和材質相同且數量巨大時用Instance來最佳化,比如草。 利用尋找紋理(LUT)來最佳化複雜的光照渲染,比如:皮膚、頭髮、噴漆等。 盡量不要使用Procedural Sky,計算瑞麗散射和米氏散射效率比較低。 盡量不要使用speedtree,改為模型加簡單樹葉動畫,不過SpeedTreeWind.cginc裡面的動畫函數很豐富,TerrianEngine中的SmoothTriangleWave很好用。 多用調試工具檢查shader效能,常用工具有:FrameDebug、Nsight、RenderDoc 、AMD GPU ShaderAnalyzer / PVRShaderEditor、Adreno Profiler 、騰訊Cube、UWA等;另外可以內建GM介面,比如開關陰影,批量替換shader等方便真機調試。 2.指令碼
減少GetComponent、find等尋找函數在Update等迴圈函數中的調用、go.CompareTag代替go.tag 、 減少SendMessage等同步函數調用;減少字串串連;for代替foreach,5.5以後版本foreach已經最佳化過了;少用linq; 大資源改為非同步載入 合理處理協程調用 將AI、網路等放在單獨線程 發布最佳化:關閉log、剔除代碼 偽隨機 指令碼掛載類改為Manager等全域類實現 lua中盡量不實現update、fixedupdate等迴圈函數,lua和csharp互調用的效率比較低。 3.記憶體管理
池子管理粒子、float UI等小資源,頻繁地GC會造成卡頓 必要時主動調用GC.Collect() 按照不同資源、不同裝置管理資源生命週期,Resources.Load和Assetbundle統一介面,利用引用計數來管理生命週期,並列印和觀察生命週期。保證資源隨情境而卸載,不常駐記憶體,確定哪些是預先載入,哪些泄漏。 記憶體流失(減少駐留記憶體):Container內資源不remove掉用Resources.UnloadUnusedAssets是卸載不掉的;對於這種情況,建議直接通過Profiler Memory中的Take Sample來對其進行檢測,通過直接查看WebStream或SerializedFile中的AssetBundle名稱,即可判斷是否存在“泄露”情況;通過Android PSS/iOS Instrument反饋的App線程記憶體來查看; 堆記憶體過大:避免一次性堆記憶體的過大分配,Mono的堆記憶體一旦分配,就不會返還給系統,這意味著Mono的堆記憶體是只升不降的。常見:高頻調用new;log輸出; CPU佔用高:NGui的重建網格導致UIPanel.LateUpdate(按照靜止、移動、高頻移動來切分);NGUI錨點自身的更新邏輯也會消耗不少CPU開銷。即使是在控制項靜止不動的情況下,控制項的錨點也會每幀更新(見UIWidget.OnUpdate函數),而且它的更新是遞迴式的,使CPU佔用率更高。因此我們修改了NGUI的內部代碼,使錨點只在必要時更新。一般只在控制項初始化和螢幕大小發生變化時更新即可。不過這個最佳化的代價是控制項的頂點位置發生變化的時候(比如控制項在運動,或控制項大小改變等),上層邏輯需要自己負責更新錨點。 載入用協程; 控制同一個UIPanel中動態UI元素的數量,數量越多,所建立的Mesh越大,從而使得重構的開銷顯著增加。比如,戰鬥過程中的HUD血條可能會大量出現,此時,建議研發團隊將運動血條分離成不同的UIPanel,每組UIPanel下5~10個動態UI為宜。這種做法,其本質是從機率上儘可能降低單幀中UIPanel的重建開銷。 資源冗餘:AssetBundle打包打到多份中;動態修改資源導致的Instance拷貝多份(比如動態修改材質,Renderer.meterial,Animation.AddClip)。 磁碟空間換記憶體:對於佔用WebStream較大的AssetBundle檔案(如UI Atlas相關的AssetBundle檔案等),建議使用LoadFromCacheOrDownLoad或CreateFromFile來進行替換,即將解壓後的AssetBundle資料存放區於本地Cache中進行使用。這種做法非常適合於記憶體特別吃緊的項目,即通過本地的磁碟空間來換取記憶體空間 4.美術
建立資源審查規範和審查工具:PBR材質貼圖製作規範、情境製作資源控制規範、角色製作規範、特效製作規範;利用AssetPostprocessor建立審查工具。 壓縮紋理、最佳化精靈填充率、壓縮動畫、壓縮聲音、壓縮UI(九宮格優於展開);嚴格控制模型面數、紋理數、角色骨骼數。 粒子:錄製動畫代替粒子、減少粒子數量、粒子不要碰撞 角色:啟用Optimize Game Objects減少節點,使用(SimpleLOD、Cruncher)最佳化面數。 模型:匯入檢查Read/Write only、Optimize Mesh、法線切線、color、禁用Mipmap 壓縮紋理問題:壓縮可能導致色階不足;無透明通道用ETC1,現在安卓不支援ETC2已不足5%,建議放棄分離通道辦法。 UI:儘可能將動態UI元素和靜態UI元素分離到不同的UIPanel中(UI的重建以UIPanel為單位),從而儘可能將因為變動的UI元素引起的重構控制在較小的範圍內; 儘可能讓動態UI元素按照同步性進行劃分,即運動頻率不同的UI元素儘可能分離放在不同的UIPanel中; 儘可能讓動態UI元素按照同步性進行劃分,即運動頻率不同的UI元素儘可能分離放在不同的UIPanel中; ugui:可以充分利用canvas來切分不同元素。 大貼圖會導致卡頓,可以切分為多個載入。 iOS使用mp3壓縮、Android使用Vorbis壓縮 5.批次
開啟static batch 開啟dynamic batch:要求模型小於900頂點,用法線小於300,用切線小於180,縮放不一致、使用lightmap、多通道材質等會使dynamic batch無效。 減少GameObject,情境模型數量對fps影響巨大。 批次不是越少越好,過大的渲染資料會給匯流排傳輸帶來壓力。 6.物理
不需要移動的物體設為Static 不要用Mesh碰撞,角色不用碰撞體 觸發器邏輯最佳化 尋路頻率、AI邏輯頻率 、Fixed Timestep、降幀到30 出現卡頓的複雜計算,例如尋路、大量資源載入 可以用分幀或者協成非同步來處理