性能調優,一直是游戲上線之前的很重要的一個環節, 游戲幀率過低,手機發燙, 低端機上跑不起來等, 這些都需要來做優化,今天我們來給大家分享Unity做性能調優的指導思想與解決方案,
這里有個unity學習交流小組點擊可以直接加入,一起學習交流吧

性能調優的指導思想
接觸過很多剛做性能調優的小伙伴,他們做性能調優最大的問題一開始就通過猜測,推斷來做性能調優,缺乏一個做性能優化的系統指導流程, 導致優化的效果不好,性能調優首先要分析問題,定位問題,證明是這塊有問題后再對癥下藥,著手優化,拿出解決對策,沒有證明問題之前,不要隨便動手優化,就像醫生,看病做手術前先做檢查,不確定問題就隨便開刀,那是極不負責任的做法,
大家可以回想一下,當幀率低的時候,你馬上就是去查Drawcall,去優化降低Drawcall,這里我想說,做性能優化之前,先定位,證明確實是Drawcall的問題導致性能下降,才動手,如何來定位問題,找出引起問題的代碼或物體呢?接下來給大家介紹一些方法,
(1)對比法
例如, 剛開始的時候幀率是60FPS,同一個場景運行一段時間以后是30FPS,如何優化,像這種符合很明顯的對比場景,我們可以通過前后對比,來找出60FPS,30FPS,最大的變化,一般可以通過打開stats, 來觀察前后主要的變化,main thread耗時,render thread耗時, 三角形面數,記憶體等資訊,看看前后明顯發生的變化,看到資料變化以后,再來思考整個程序中代碼做了哪些事情,出現過哪些物體,最可能出的問題的地方,然后再證明, 只有證明了問題的存在,再著手優化,
(2)隔離法
這個是我經常用的一個方法, 就是隔離可疑區域和代碼,然后比較,逐步排查,縮小問題范圍,隔離法其實是非常好的方法,看上去很笨,很慢,但其實效率遠比你想像的要好,比如,場景的物體過多,這個問題,那么我就可以采取隔離方法,先減少掉一倍,看效果,某個代碼引發了幀率下降,可以逐步的注釋掉代碼,來觀察結果,隔離的時候,可以采用二分查找,一半一半的排查,排查范圍很快被縮小,問題也就精確的定位了,
(3)反經驗法
上面介紹了常用的兩種方法,定位問題,還有其他的一些方法,但我更想說的就是反經驗法,你沒看錯,反經驗,在性能優化的時候,不要過分相信經驗,一步一步的逐步分析,有條不穩,不管什么問題,按部就班,不要根據經驗,武斷的下結論,要嚴格證明問題所在后再動手, 很多小伙伴遇到性能問題后,把問題簡單的描述一下,去請教一個經驗豐富的人,問他可能是哪方面的問題,根據他的猜測,你來優化,這種方式是很難做好你專案的性能優化的,專案和專案都不一樣,連具體的問題都沒有定位,你去請教經驗豐富的老者,從老者的角度來說也無法幫到你,不要迷信經驗,在動手前一定要定位好誰的問題,然后才能針對具體問題下對策,
優化架構, 標準規范化開發流程
好的框架設計,不僅讓大家能很好的在一起作業,同時更方便我們快速的反應和定位問題,你的專案不好定位問題,那么一定是框架設計做的不好,所以開始做專案的時候,框架設計要花點時間,模塊盡可能的獨立,模塊入口盡量清晰,整個框架設計能很好的隔離錯誤的蔓延,資源視圖與邏輯代碼分離,游戲資料與代碼邏輯分離,這些都有助于快速的定位問題,比如我要驗證是否物體過多,導致性能問題,只要在表格上配置一下,少放一些物體就可以驗證,如果覺得是某個功能,導致消耗CPU,可以把物體的這個功能的組件關倍訓不添加,比如懷疑怪物AI,可以注釋掉添加怪物AI的組件,來證明,好的框架設計,在定位問題的時候,就變得非常簡單,如果是ECS,定位會更加簡單,記憶體看Entity與資源,演算法性能看System與物體規模……
接下來要給大家介紹的是我認為最重要的經驗,就是標準化,規范化專案開發進度和流程, 把性能問題一開始就放到日常專案開發中,我帶專案的時候,每個禮拜至少做一次發布版本的測驗,包含各個平臺,不同的手機等,嚴格監測性能各項資料,哪個禮拜出現性能問題,馬上可以回溯,復盤資料,著手摸清楚并解決,盡快修正,專案立項后,盡快的驗證核心玩法極限時的性能開銷與測驗,不要等游戲專案做完了,才去驗證,在設計初期驗證完成后,針對一些性能問題組織技術公關,可能還要修改策劃需求和玩法, 早期把性能問題盡快越早摸清楚,是確保整個專案成功上線的關鍵,不要等到上線了才到各平臺做測驗,那個時候功能多了,不知道有些問題是從什么時候開始就有的,標準的嚴謹的開發流程,伴隨專案監控性能資料,盡快驗證核心玩法,提前引入測驗, 讓我們整個專案開發做到有問題盡早發現,盡早糾正,

Unity 性能優化方法集錦
講完指導思想,和開發流程這些宏觀問題后, 我們再來討論一些具體問題的常用的優化方法,
(1)包體體積優化:
聲音檔案優化
將wav,壓縮成mp3或ogg, 最好是ogg,沒有著作權問題, 將多聲道變成單聲道,改變聲音的采樣率與碼率,減少聲音檔案體積,
字體檔案優化
盡量多使用系統字庫,這樣不用額外帶字體檔案,可以使用一些位圖字庫,來替代額外的字庫,如果你的文本內容是固定的,可以對字庫進行裁剪,把不用的字從字庫里面洗掉掉,減少自帶字庫的體積,
貼圖檔案大小優化
將png轉jpg, 并使用圖片壓縮軟體,壓縮貼圖體積, 盡量減少圖片數目,復用圖片,盡量能使用顏色等代碼的方式來代替貼圖,
3D模型檔案
根據需求適當降低模型面數, 去掉多余不用的資料, 可以通過法線貼圖,高度貼圖等將低模做出高模的效果, 合并貼圖通道資料(PBR作業流中,將金屬度,粗糙度,環境遮擋放一個紋理里面, 將資料合并到貼圖不用的通道,比如Albedo貼圖,Alpha通道不用,可以存放環境遮擋等,節約貼圖數目),
將資源ab包化
把所有的資源分成一個一個的ab包,ab包本身有壓縮功能,這樣整體的包體也會減小,如果可能,可以把ab包全部或部分放服務器,第一次運行游戲的時候再下載,比如《王者榮耀》,這樣來節省包體體積,
(2): 骨骼影片優化:
3D游戲中骨骼影片也是非常消耗性能的地方,因為每幀,我們都要通過影片組件采樣,采樣后重新計算出來我們的頂點的位置,傳給GPU的渲染管線來處理繪制, 我們可以將骨骼影片的每幀頂點的位置快取到一個紋理貼圖里面,用空間換時間的方式來節約影片組件的開銷,并嘗試合并Drawcall,
(3): LOD的優化:
對于大規模多角色的場景游戲,我們要開啟LOD,讓遠處的物體用盡量少的面,近處的物體用更多的面, 來提升我們運行時候的性能,
(4): 使用3D模型細節增強,提升計算性能:
使用法線貼圖,高度貼圖等細節增強手段來降低模型的面數同時,能獲得和高模同樣的細節和更好的計算性能,
(5): 光照優化:
靜態光照烘培+反射探頭來做更好的場景效果,代替實時的光照計算,減少光源的數目,對于一些物體的發光特效,可以通過shader來實作,而不用加光源,定制Shader,可以將逐像素光照改為逐頂點光照,節約逐像素光照的計算開銷,
6: SetPassCall與Drawcall優化
SetPassCall
SetPassCall通俗的講就是更換重新裝載在渲染管線里面的Shader代碼和配置,就像換畫筆一樣的,SetPassCall開銷非常的大,所以盡可能的要少用一些不同的Shader,在一個場景里面,盡可能的讓同一個Shader 繪制最多的物體后再切換下一個Shader的物體,盡量避免繪制物體的時頻繁交叉的來回切換Shader,節約SetPassCall的次數,
DrawCall
DrawCall 優化,其實很簡單, 三種優化手段,靜態合批,動態合批,GPU Instancing合批, 然后我們針對合批的條件去達成對應的條件就可以了,比如,我們做一個捕魚達人3D游戲,我們有很多的魚,可以把魚的所有紋理貼圖,放到一個大圖里面,這樣,這些魚就是同樣的Shader,同樣的紋理貼圖物件,就可以達到合批的條件而做到合批, 節約Drawcall,
(7): 物理引擎的優化:
能不用物理引擎的游戲,盡量不用物理引擎,能自己實作的盡量用代碼自己實作,因為物理引擎的開銷畢竟擺在那里了, 物理引擎使用很簡單,但是性能開銷也不可忽視,有一些不是真正的物理游戲,比如Moba類的游戲,防止物體穿透等,其實我們可以不用物理引擎,通過制作地圖格子的方式,標記障礙物,自己控制的時候,如果進入障礙物的標記,就不讓它更新位置即可,這些可以替換物理引擎獲得很好的性能效果,常用的有菱形的地圖格子與六邊形的地圖格子,
暫時不用的剛體,或者不在視線范圍內的剛體可以根據游戲的需要,顯示和隱藏,達到節約物理引擎計算的目的,修改物理引擎全域的迭代引數,獲得實用性的同時又有更好的性能,了解物理碰撞器的性能開銷,球體碰撞器最小,網格碰撞器最大,盡量使用開銷小的碰撞器, 對于靜態物體,能夠合并物理碰撞器的盡量用一個物理碰撞器,
(8): 陰影的優化:
通過開關控制陰影,在低端機上關閉陰影獲得更好的運行幀率,在高端機上開啟陰影,獲得更好的運行效果,通過偽陰影技術來做貼圖,節約陰影計算的開銷, 可以自己定制Shader來實作高性能的陰影效果,
(9): Shader優化:
減少Shader中的條件判斷和展開回圈,來獲得更好的指令緩沖cache 命中率, 減少一些復雜的計算,可以采用一些空間換時間的方法來快取計算結果,逐頂點計算來替代逐片元的計算,減少計算次數,可以把Shader 設定為常駐記憶體快取,這樣節約SetPassCall所帶來的開銷,
10: C#良好編碼習慣與演算法思想
Update里面盡量不要使用GetComponent, Find等,可以在初始化的時候先找出來,能放Update里, 盡量不放FixedUpdate, 這樣低端機上能節約計算次數,全域設定,降低FixedUpdate每秒呼叫迭代的次數,節約FixedUpdate迭代時的計算時間,避免大量反復的new 物件,一些重復使用的物件,可以通過節點池等先反復使用,避免重復創建與釋放,
可以用多執行緒來做一些計算,避免卡住main thread游戲執行緒導致幀率下降,不要在游戲主執行緒里面直接做同步的IO以免卡住游戲執行緒,導致幀率下降,
從開始寫代碼起,要把每行代碼寫好,長期的堅持積累,才能形成良好的代碼習慣,寫出高性能,高質量,高效率的代碼,學好資料結構與演算法,能很好的分析演算法的時間復雜度,空間復雜度等,
經過上面的一些討論,可能還會有很多優化技巧,歡迎大家留言討論,同時我們有很多免費的Unity 性能優化的視頻課程,供大家可以學習,成為優化優化的高手,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/291577.html
標籤:其他
上一篇:C語言實作三子棋游戲
下一篇:#自制游戲#遠古版本
