Prefab 最佳化:向預製體打出最有效的組合拳

侑虎科技發表於2020-12-16

在上一期《粒子系統優化:Mesh模式下的優化策略》中,我們針對粒子系統中和網格相關的優化注意點和大家做了解釋。這些看似細小的知識點,很容易在大家的開發和學習過程中被疏忽,而長期的問題積累最終都會反映到專案的效能表現上。為此,我們將這些規則列出,並且以一個個知識點的形式向大家逐一解讀。

本期,我們將講解UWA本地資源檢測中針對預製體(Prefab)進行檢測的規則:“使用了MotionVector的SkinnedMeshRenderer”、“使用Tiled模式的Image元件”和“不可見的Image元件”。我們將力圖以淺顯易懂的表達,讓職場萌新或優化萌新能夠深入理解。

1、使用了MotionVector的SkinnedMeshRenderer

Prefab 最佳化:向預製體打出最有效的組合拳

首先我們先理解一下Unity裡面的“骨骼動畫”。它的概念很貼近現實中的“骨骼”的含義:常見的模型被分解為兩個部分:骨骼Bones和蒙皮Mesh。這些以“關節”結構連線在一起的骨頭為模型構建起了一套骨架;隨著骨架結構的運動變化,模型表面的蒙皮網格也會隨著骨架的變動而發生改變。

這種以骨骼位置變動為核心的動畫就是骨骼動畫。相較於關鍵幀動畫和關節動畫,Bone animations目前在Unity中應用極其廣泛。

在Unity中,如果匯入的模型有骨骼動畫,那麼Unity就會自動為對應的網格新增上Skinned Mesh Renderer,來渲染這些骨骼動畫。蒙皮網格渲染器元件會將模型的網格(Mesh)與骨骼節點繫結起來,當骨骼動畫播放時,網格的頂點會隨著它所繫結的骨骼進行運動,這便形成了“皮膚”隨骨骼運動的效果。在Inspector介面可以對該元件進行一系列配置。

Prefab 最佳化:向預製體打出最有效的組合拳

其中有一項屬性就是本條的主角:Skinned Motion Vector。

Prefab 最佳化:向預製體打出最有效的組合拳

運動向量(Motion Vector)的概念來源於視訊壓縮領域,在維基百科中有如下解釋:

In video compression, a motion vector is the key element in the motion estimation process. It is used to represent a macroblock in a picture based on the position of this macroblock (or a similar one) in another picture, called the reference picture.

通俗地理解,運動向量描述了在螢幕空間中,每個畫素所對應的物體在連續兩幀之間的運動“速度”,該“速度”值等於該畫素塊在這幀的位置減去在上一幀的位置,也就是當前畫素下的片元在相鄰兩幀之間,螢幕空間位置的差。運動向量的示意圖如下:

Prefab 最佳化:向預製體打出最有效的組合拳
來源:維基百科

Unity中,在Mesh Renderer與Skinned Mesh Renderer元件中都可以開啟Motion Vector,用以獲取物體的運動資訊。若開啟,相機會在渲染管線中增加一個motion vector pass,將運動向量渲染在一個Buffer當中,使用者可以將Shader指令碼中這個Buffer用於後處理特效。

Motion Vector一般會用於運動模糊這樣的後處理特效、基於時間的抗鋸齒演算法(temporal antialiasing)等。但是Motion Vector帶來的視訊記憶體中的雙倍buffer開銷和運算量開銷是不容忽視的。而Skinned Motion Vector在移動端專案當中的應用也是很少的,一般不建議開啟。

所以,在本條規則篩選出對應的Skinned Mesh Renderer後,開發團隊需要根據實際情況決定是否勾選對應骨骼動畫的Skinned Motion Vector。


2、使用Tiled模式的Image元件

Prefab 最佳化:向預製體打出最有效的組合拳

首先我們需要了解UGUI,一言以蔽之:UGUI是Unity官方開發的UI系統。對它的理解,要放大到最基本的“介面”的含義:它能幹很多事,常見的功能選單,開啟的按鈕,主介面上的模組的顯示,等等,都會用到這個UGUI。

Prefab 最佳化:向預製體打出最有效的組合拳

而Image元件,也就是影像元件,最常用於顯示非相互性的影像,相信大家在日常的開發過程中並不陌生,我們就不再展開講了。在我們將貼圖(必須是Sprite哦)拖入Source Image後,我們就可以在Inspector皮膚設定Image Type。

Prefab 最佳化:向預製體打出最有效的組合拳

此時有一種情況很容易被大家忽略:當Image.Type為Tiled時,如果我們使用的Texture的WrapMode不是Repeat,那麼Unity在處理時,就會通過生成多個面片的方式來實現平鋪效果。

Prefab 最佳化:向預製體打出最有效的組合拳

Prefab 最佳化:向預製體打出最有效的組合拳

在Image.Type為Tiled模式的前提下,兩圖的左側是Texture為Repeat模式的效果展示與網格顯示;右側是Texture為Clamp模式的效果展示與網格顯示。

這樣我們就無意間增加了面片數量。一旦我們在Image元件裡我們不注意這個問題,那麼量變引起質變,在整個專案裡這些額外多出來的面片就會在執行時導致額外的計算壓力和渲染消耗。

所以在找出這些使用了Tiled模式的Image元件後,開發團隊需要對匯入的Texture的WrapMode和Image元件的Type型別進行進一步的檢查,以避免上述情況的發生。


3、不可見的Image元件

Prefab 最佳化:向預製體打出最有效的組合拳

本條規則其實和上一條類似,問題的著眼點都是匯入到Image元件內的Texture資源。在之前的文章《紋理優化:不僅僅是一張圖片那麼簡單》中,我們對Alpha通道有過簡單的描述。

此處我們談論一下Alpha值全為0的情況。Alpha值恆為0,說明Texture為全透明狀態,視覺上的紋理表現其實為“不存在、看不見”,但對專案和計算而言,它依然存在並佔有相關的記憶體和開銷。

當我們把全透明的Texture匯入到相關Image元件後,Image元件也會表現為“視覺上消失,物理上存在”,這種情況下,影像元件沒有對專案產生展示效果上的貢獻,反而帶來了效能上額外的佔用與計算消耗。

所以藉助本條規則的篩選,開發團隊可以最大限度地避免這種情況的發生。當然,我們不能武斷地排除Image元件不視覺化的特殊應用,開發團隊還是要根據專案的實際需求來決定這些Image元件的“生與死”。


希望以上這些知識點能在實際的開發過程中為大家帶來幫助。大家其實可以發現,看似各個獨立的部分:網格、粒子系統、材質和紋理等,其實在優化上都有著互相的關聯。所以面對專案優化,開發團隊要以一個整體的高度去看待專案的各個部分。

需要說明的是,每一項檢測規則的閾值都可以由開發團隊依據自身專案的實際需求去設定合適的閾值範圍,這也是本地資源檢測的一大特點。同時,也歡迎大家來使用UWA推出的本地資源檢測服務,可幫助大家儘早對專案建立科學的美術規範

Prefab 最佳化:向預製體打出最有效的組合拳

往期優化規則,我們也將持續更新。
《動畫優化:關於AnimationClip的三兩事》
《材質優化:如何正確處理紋理和材質的關係》
《紋理優化:讓你的紋理也“瘦”下來》
《紋理優化:不僅僅是一張圖片那麼簡單》

萬行程式碼屹立不倒,全靠基礎掌握得好!

效能黑榜相關閱讀

《那些年給效能埋過的坑,你跳了嗎?》
《那些年給效能埋過的坑,你跳了嗎?(第二彈)》
《掌握了這些規則,你已經戰勝了80%的對手!》

相關文章