unity fixedupdate_unity相关
會頻繁更新 主要給自己看
性能優化總結:成本和分析
工具:Memory Profiler/Unity Editor Profiler/Frame Debugger/RenderDoc/ VS / ADB /Instruments / GPA /Inter VTune Profiler /Unity Bulid Report Tool
優化大綱:
1:CPU
(1)渲染模塊
簡化資源:
- Back Face Culling(把看不到的三角面剔除)
- Facing Culling(把看不到的區域剔除)
- Cull Distance Volume(基于距離的Culling)
- Landscape Culling Settings(地形剪裁Culling)
- LOD & HLOD (數據剪裁Culling)
- Streaming System(數據占用Culling)
- Precomputed Visibility Volume (離線Culling緩解實時Culling的壓力)
降低DrawCall:
- 靜/動批處理
- 圖集:把UI的圖片打成圖集 減少DrawCall 但相應的可能會導致資源都大 加載的時候可能會加載多余的資源到內存但又不使用 解決辦法就是根據功能去分類打圖集 并且圖集要進行合理安排 像背景這種大圖片就不需要打進去了 盡量使得合圖盡量減少空白 并且保持合圖不會特別大
- GPU Instance技術
動態批處理要求
- 頂點屬性的最大限制為900,而且未來有可能會變。不要依賴這個數據。
- 一般來說,那么所有對象都必須需要使用同一個縮放尺度(可以是(1, 1, 1)、(1, 2, 3)、(1.5, 1.4, 1.3)等等,但必須都一樣)。但如果是非統一縮放(即每個維度的縮放尺度不一樣,例如(1, 2, 1)),那么如果所有的物體都使用不同的非統一縮放也是可以批處理的。這個要求很怪異,為什么批處理會和縮放有關呢?這和Unity背后的技術有關系,有興趣的可以自行谷歌,比如這里。
- 使用lightmap的物體不會批處理。多passes的shader會中斷批處理。接受實時陰影的物體也不會批處理。
合批常遇問題解決:
- Mask影響合批 如果遮罩區域只是矩形的話直接替換成Rect2DMask 如果還是想用不規則圖片做遮罩的話直接重寫mask
(2)UI模塊
- 不需要Graphic Raycaster的關閉掉
- 動靜分離
- 提高填充率:(1)把透明圖片按鈕用其他方式替換掉 (2)把圖片的空白透明的地方干掉
- 全屏界面時關閉3D渲染(把3D場景的攝像機關閉)和畫布
- 停止在界面外的UI渲染
- 變化的UI會影響合批,建議:根據更新頻率把不同的UI分布到不同的畫布上 Z軸保持一致 相同材質和使用矩形裁剪(mask裁剪會影響合批 且因為其是模板測試的方式裁剪導致像圓形頭像這種裁剪完會有鋸齒)
(3):加載模塊
根據不同的資源特點使用不同的加載方式 比如:緩存 流式加載 異步加載 多線程等
- Resources會影響啟動速度 因為文件的標題會變成所有資源的索引表 這個索引表會在游戲開始后載入內存 以更有效的方式進行資源管理和卸載 比如熱更新常用的assetbundle資源管理
(4):代碼效率
對耗時的代碼進行優化
- 更改參數或者替換算法來降低算法復雜度 比如:排序算法 查找算法等
- 給外部材質傳遞參數的時候我們往往會直接根據字符串名直接傳遞 但其內部其實是ID 頻繁調用會導致多次轉換 所以我們會需要先把字符串轉成ID并且緩存下來在使用
- GetComponent會遍歷對象上面的所有組件去尋找 組件越多GetComponent的成本就越高 Find會尋找遍歷當前場景所有對象 對象越多成本越高 建議使用緩存的方式優
- 通過坐標轉換來移動有剛體組件的對象會導致PhysX物理引擎整體重新計算 建議用rigidBody自帶的方法并且放到FixedUpdate去
- AddComponent會有一系列的檢查過程 為了減少這些過程 建議不要在運行時在去AddComponent一些組件 而是預先制作好預設體
- 移除空的Unity事件函數 因為其依然在內部經行一系列操作
- Awake和Start完成后才會開始游戲 初始化內容太多會導致啟動速度變慢 建議啟動游戲時初始化內容較少 進入游戲在開始各種初始化過程
- 層級太深會導致父物體變化,所有子物體跟著變化,而且垃圾回收也需要遍歷很多次才能拿到所有對象
2:內存優化
資源優化:
GC優化(值類型的內存是由stack分配的 引用類型的內存是heap分配的)
(1)定期調用GC:比如場景切換的時候就進行一次GC操作
(2)stack(堆棧) 包含:函數本身,函數傳的參數,函數區域的變量 用完就從堆棧里面丟出去 太多會造成堆棧溢出
- 在編輯器時候才使用get/set(因為get/set屬于方法調用 花費在堆棧框中的時間會增加) 真機上就正常獲取數據
(3)heap(堆) 包含:類,實體,對象 用完只會標記為未使用 需要使用垃圾回收器去回收
- 緩存:對于不會變化的對象預先緩存下來,后面可以重復使用 比如使用Scriptable Objects減少我們自己寫的類的里面的變量數據在new的時候多次生成
- 對象池:預先實例化n個對象 循環使用這幾個對象 多了就擴容
(4)以下這些操作會造成內存分配 用的時候要盡量避免或者用其他方法代替
- 干掉非必要的Log日志打印
- 字符串拼接,unity部分API(太多,可自查,這里不放了),裝箱操作,協程,foreach(unity5.5之前),函數引用,LINQ和常量表達式
- struct的結構如果有值類型和引用類型的話 需要分開他們
- 遇到對象引用其他對象的可以使用標記來代替引用
引擎模塊自身占用:
對于WebStream和SerializedFile,你需要關注以下兩點:
- 是否存在AssetBundle沒有被清理干凈的情況。開發團隊可以通過Unity Profiler直接查看其使用具體的使用情況,并確定Take Sample時AssetBundle的存在是否合理;
- 對于占用WebStream較大的AssetBundle文件(如UI Atlas相關的AssetBundle文件等),建議使用LoadFromCacheOrDownLoad或CreateFromFile來進行替換,即將解壓后的AssetBundle數據存儲于本地Cache中進行使用。這種做法非常適合于內存特別吃緊的項目,即通過本地的磁盤空間來換取內存空間。
無效的Mono堆內存開銷
避免或減少過多“無效堆內存":
- 避免一次性堆內存的過大分配。Mono的堆內存也是“按需”逐步進行分配的。但如果一次性開辟過大堆內存,比如New一個較大Container、加載一個過大配置文件等,則勢必會造成Mono的堆內存直接沖高,所以研發團隊對堆內存的分配需要時刻注意;
- 避免不必要的堆內存開銷。
資源冗余:干掉多余重復的資源
- 變體優化:表面著色器改成vert/frag 去掉不需要的變體和Pass
- 去掉多余重復的資源
內存泄露查詢方法:
- 檢查資源的使用情況,特別是紋理、網格等資源的使用
- 通過Profiler來檢測WebStream或SerializedFile的使用情況
- 通過Android PSS/iOS Instrument反饋的App線程內存來查看
4:渲染優化
- 方案替換(陰影 抗鋸齒 后處理等實現方法多種多樣,可以挑選一個最適合項目的)
- 加速結構(運用數據結構的特性加速運算,比如:層次包圍盒)
- 加速算法(運用數學的特性加速運算,比如:重要性采樣)
- 算法優化:減少ifelse,clip使用 避免除0 符號替換(比如:除法換乘法 乘法換加法) 使用RTT代替GrabPass等
- OverDraw:相機和場景分開 不透明物體從后往前 Early Depth testing(提前深度測試) 增加填充率
5:資源制作過程優化
- 移除不需要透明度的紋理的alpha通道
- 合并mesh/貼圖減少內存和構建時間
- 底模仿高模
6:編譯速度優化
- 代碼固定的可制作成DLL
7:其他
- 自定義分辨率而不是使用手機自帶的(因為現在的手機分辨率越來越大,但我們其實并不需要那么大)
- 數據結構選擇
總結
以上是生活随笔為你收集整理的unity fixedupdate_unity相关的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python编程定义圆_Python语言
- 下一篇: 怎么安装python2.7_如何在Win