Unity性能優化概述
性能優化不是某個環節的極致壓榨,而是所有模塊的協同共進。本文將為你建立完整的Unity性能優化知識體系。
很多Unity開發者一提到性能優化,首先想到的就是Draw Call、Batches這些渲染指標。這沒錯,但它們只是性能優化中的一部分。真正的性能優化是一場全方位的戰役,涉及CPU、GPU、內存、資源管理和代碼質量等方方面面。
性能優化的核心:木桶理論
一個游戲的性能表現,如同一個木桶的容量,不取決于最長的那塊木板,而取決于最短的那塊。我們可以將渲染優化到極致(Batches極少),但一段糟糕的腳本或一個內存泄漏就足以讓游戲卡頓甚至崩潰。
全局性能優化檢查清單
為了幫助你系統地進行優化,可以遵循下圖的全局性能優化檢查流程來定位和解決問題:
下面,我們粗過流程中提到的各個模快優化點。
一、CPU性能優化
CPU是游戲的大腦,負責處理邏輯、物理和渲染指令。CPU瓶頸通常表現為Profiler中CPU主線程出現高峰。
1. 腳本優化
- 優化Update邏輯,將不必要的計算移出Update或降低其執行頻率:避免在
Update
、FixedUpdate
、LateUpdate
中執行繁重操作(如查找對象、計算復雜算法)。 - 緩存引用:使用
GetComponent
、Find
等方法獲取的引用,應在Start
或Awake
中緩存,避免每幀查詢。 - 協程與異步:合理使用
Coroutine
和異步操作(async/await
)處理延時任務,避免阻塞主線程。
2. 物理優化
- 簡化碰撞體:堅決不使用
MeshCollider
,多用BoxCollider
、CapsuleCollider
等原始碰撞體組合。 - 減少剛體:僅為需要物理引擎驅動的對象添加
Rigidbody
。靜態物體設為Static
。 - 調整頻率:通過修改
Time.fixedDeltaTime
提高物理更新間隔,非物理游戲不必保持0.02s。 - 優化碰撞層:在Physics Settings中設置層碰撞矩陣,禁用不必要的層間碰撞。
3. UI優化
- 減少Canvas重建:UI元素的變化(位置、顏色、文本)會觸發Canvas重建。將頻繁變化的UI元素放在獨立的Canvas上。
- 禁用Raycast Target:對于不需要點擊事件的Image/Text,取消勾選
Raycast Target
,減少不必要的射線檢測。 - 對象池化列表:對滾動列表使用對象池(如Unity的
ScrollRect
循環列表),避免頻繁實例化/銷毀。
4. 動畫優化
- 簡化Animator:避免使用過于復雜的Animator Controller,減少狀態和過渡的數量。
- 使用動畫裁剪:對不可見的角色(如遠處的NPC),通過
Animator.cullingMode
停止其動畫更新。
二、GPU性能優化
當CPU很空閑但幀率依然不高時,瓶頸就在GPU。
1. 渲染優化
- 降低Batches:這是核心目標。通過靜態合批、GPU Instancing、SRP Batcher等技術,減少Draw Call。
- 降低SetPass Calls:減少材質種類。使用紋理圖集(Sprite Atlas) 讓多個物體共享同一材質。
- 使用LOD:為復雜模型配置LOD Group,根據距離相機遠近顯示不同精度的模型。
- 啟用遮擋剔除:使用Occlusion Culling,避免渲染被遮擋的物體。
2. 填充率與Overdraw
- 控制分辨率:對于移動設備,適當降低渲染分辨率是最直接的優化方式。
- 簡化后處理:屏幕后處理效果(如Bloom、SSAO)非常消耗性能,務必謹慎使用。
- 警惕透明物體:半透明物體疊加會導致像素被多次繪制(Overdraw)。應盡量減少透明區域的面積。
3. 著色器與光照
- 選擇移動端Shader:為移動平臺使用輕量級的Shader(如
Universal Render Pipeline/Simple Lit
)。 - 優化光照:減少實時光源的數量,多用烘焙光照(Baked Lightmap)。
- 簡化粒子特效:控制粒子系統的最大粒子數、發射頻率和重疊程度。
三、內存與資源優化
內存問題不會直接導致幀率下降,但會引發卡頓(GC)和崩潰,尤其影響移動設備。
1. 資源管理
- 紋理優化:使用壓縮格式(ASTC),尺寸設為2的冪次方,關閉不必要的
Read/Write
選項。 - 音頻優化:使用壓縮格式(Vorbis),將
Load Type
設置為Compressed In Memory
,避免WAV文件。 - 模型優化:在建模軟件中減少面數,導出時開啟壓縮選項。
2. 資產生命周期管理
- 使用對象池:對于頻繁創建和銷毀的對象(子彈、敵人、特效),使用Object Pooling模式復用。
- 管理AssetBundle:動態加載和卸載資源包,及時調用
Resources.UnloadUnusedAssets
。 - 避免內存泄漏:注意靜態變量、事件監聽等對對象的引用,防止其無法被GC回收。
3. 代碼質量與GC
- 避免GC分配:杜絕在Update中
new
對象、使用字符串連接(如Debug.Log
)、Lambda表達式等。多用結構體(Struct)和緩存。 - 使用值類型:對于小型、短暫的數據,使用
Struct
而非Class
,因為它們分配在棧上,不會觸發GC。
總結:性能優化的方法
- 不要猜測,要 profiling:Unity Profiler是最強大、最權威的工具。任何優化決策都應基于Profiler的數據。
- 確立目標:不同平臺(PC、移動端、VR)的性能標準天差地別。先明確你的目標幀率和設備。
- 迭代優化:優化是一個“分析 -> 修改 -> 驗證”的循環過程,而非一蹴而就。
- 全局思維:時刻記住木桶理論,確保CPU、GPU、內存三大核心均衡發展,沒有明顯短板。