Asset auditing - 資源審查html
許多項目發生效能問題的真正緣由只是因爲人員操做不當或是試東試西,而不當心改到導入設定影響到導入的資源。(例如最近的gitlab慘案)
對於較大規模的項目,最好準備一道自動的防線防範人爲失誤。例如寫一段簡單的檢查程序確保沒有任何人能在項目加入一張沒壓縮的 4K 貼圖。
或許你會以爲不可能,但這問題咱們真的很常見。沒有壓縮的 4K 貼圖會佔用大約 60mb 的內存空間,在低端的手機設備(例如 iPhone 4s)上,整個項目用掉超過 180mb~200mb 就會很危險。有時候你的遊戲在好的手機上跑沒問題,在差的手機上跑會宕機,不必定是硬件的問題。若是犯這種錯誤,這張貼圖會無故佔用應用程序四分之一到三分之一的可用內存,形成很難追蹤的內存不足錯誤。
雖然上面有提到能夠用 Unity 5.3 的 MemoryProfiler 來追蹤這樣的問題,但最好養成良好開發習慣排除這樣的可能。 git
使用資源後處裏器(Asset Postprocessors)
Unity 編輯器裏的 AssetPostprocessor 類別能夠用在 Unity 項目上實行某些基本限制。這個類別在資源導入時會收到一個回調。使用方法即繼承 AssetPostprocessor 並實做一個或多個 OnPreprocess 方法,重要的包含: 多線程
OnPreprocessTexture 編輯器
OnPreprocessModel ide
OnPreprocessAnimation gitlab
OnPreprocessAudio 動畫
請查詢 AssetPostprocessor API 文件以瞭解更多關於 OnPreprocess 方法的數據。 spa
1
2
3
4
5
6
7
8
9
10
|
public
class
ReadOnlyModelPostprocessor : AssetPostprocessor {
public
void
OnPreprocessModel() {
ModelImporter modelImporter = (ModelImporter)assetImporter;
if
(modelImporter.isReadable) {
modelImporter.isReadable =
false
;
modelImporter.SaveAndReimport();
}
}
}
|
這是一個簡單的 AssetPostprocessor 限制規則範例
每當導入模型到項目或模型的導入設定(Import settings)被修改時會呼叫這個類別,這裏程序只是檢查能否讀寫模型的設置 isReadable 屬性,若是是 true 就會改成 false,存盤後從新導入資源。
請注意,呼叫 SaveAndReimport 會致使這段程序會被再次呼叫!但因爲設置已經被改成 false,因此不會無窮遞歸下去。
至於爲什麼要拿掉寫入的設置會在底下的模型章節解釋。 線程
常見資源規則設計
Textures - 材質
關閉 Read/Write Enabled 設置
這個 Read/Write Enabled 的設置會形成貼圖在內存裏變成兩份,一份在 GPU 上一份在 CPU 能夠尋址的內存上。這是由於大多數平臺,把數據從 GPU 內存讀回 CPU 很慢。從 GPU 內存讀取一張貼圖到暫存區給 CPU 程序用(例如:Texture.GetPixel)會致使效能不好。這個設定在 Unity 裏預設是關閉的,但要避免誤勾這個選項。
Read/Write Enabled 只有在 Shader 之外的地方存取貼圖數據(例如:Texture.GetPixel 和Texture.SetPixel 這樣的 API)時纔會須要,但儘可能避免使用這個功能比較好。
若是能夠,儘可能不要用 Mipmaps
對於對象相對於鏡頭之間的 Z 軸深度不太會有變化的對象,關閉 Mipmaps 能夠省下約三分之一的內存空間,但若是對象在鏡頭看出去的深度會有變化,關閉 Mipmaps 會影響到 GPU 貼圖取樣的效率。
通常來講,關閉這個選項對於 UI 和不太會變大變小的貼圖頗有幫助。
壓縮所有貼圖
針對各個不一樣的平臺選用該平臺適合的壓縮格式壓縮貼圖,這是節省內存的首要之務。
若是選到目標平臺不支持的格式,Unity 會在 CPU 上解壓縮貼圖,消耗 CPU 時間和不少內存。這類問題比較常發生在Android 上,開發者得注意 Android 裝置上各類不一樣的芯片各支持哪一種壓縮格式。
強制貼圖大小
這雖然是件小事但不少人會忘記調整貼圖大小或不當心從改到導入設定裏的貼圖大小上限。先決定各類貼圖的合理大小上限而後用程序去強制限制它。
大多數的手機遊戲用 2048x2048 或 1024x1024 來存放圖集(Atlas)就夠了,3D 手機遊戲的模型貼圖用到 512x512 應該就夠好了。
Models - 模型
關閉 Read/Write Enabled 設置
這個選項的運做原理和貼圖同樣,只不過預設是打開的。
當項目執行時想用程序來修改 Mesh,或者若是 Mesh 要用做 MeshCollider 的話,這裏須要打勾。反之若是模型沒用在MeshCollider,也沒用程序來修改 Mesh 的話,關閉這裏能夠省下一半的內存。
非角色模型關閉骨架功能
在預設狀況下,Unity 會幫非角色的模型放入一個通用骨架(Generic rig),若是這個模型執行時被實例化,會致使被加上一個 Animator 組件。若是這個對象沒有用到 Mecanim 動畫系統就會產生沒必要要的開銷,由於全部啓動中的 Animator 每幀都會被觸發一次。
關閉沒有動畫的對象的骨架來確保他們不會在執行期間被加上 Animator 組件,形成沒必要要的消耗。
幫帶有動畫的對象開啓 Optimize Game Objects 選項
OptimizeGame Objects 選項對於帶動畫的模型有明顯的效能影響。若是這裏沒打勾,在初始化模型時 Unity 會把整個模型的骨架結構對應的 GameObject 階層所有產生出來。這個巨大的 Transform 組件結構更新起來天然很耗效能,尤爲是若是結構帶有其餘組件(例如粒子系統或碰撞體)。它也會拉低 Unity 多線程對蒙皮(Mesh skinning)和骨架動畫的計算能力。
打勾後全部的骨架對應的 Transform 結構都會被移除,若是模型骨架結構中有特定的部位須要露出方便控制(例如模型的手部要用來握住武器),則能夠把它列在「ExtraTransforms」白名單中。
更多數據能夠參閱官方手冊關於 Model Importer 的部分。
若是能夠,儘可能使用Mesh壓縮
開啓 Mesh compression 選項會縮短用來表示模型數據不一樣信道的浮點數字元長度,這會移除必定的精確度並可能形成可見的變化,使用這個以前最好先讓美術檢查過這種損失在容許範圍內。
各個壓縮等級使用的位長度在 ModelImporterMeshCompression 腳本里有介紹。
請記得,能夠針對不一樣信道使用不一樣等級的壓縮,因此項目能夠只針對切線向量(Tangent)和法向量(Normal)壓縮但不壓縮 UV 和頂點位置。
追記:Mesh Renderer 的設定
當加入一個 Mesh Renderer 到 Prefab 或 GameObjec t時,請當心上面的設定。預設狀況下 Unity 會開啓 Shadow casting、Shadow receiving、Light Probe 取樣、Reflection Probe 取樣和動態向量(Motion Vector)的計算。
假如項目不須要上述的功能,記得寫個編輯器腳本關掉素材上的選項,執行期用程序加 MeshRenderer 到對象上也要記得執行相同的規則。
對於一個2D遊戲來講,不當心加了一個帶有 Shadowcasting 的 MeshRenderer 到場景裏會觸發整個陰影計算循環,這一般是浪費效能。
Audio - 音效
採用平臺支持的壓縮設定
採用硬件支持的音源壓縮格式。全部的iOS設備都有 MP3 硬件解壓縮能力,而大多數的 Android 設備都有支持 Vorbis。
此外,能夠直接將未壓縮的聲音文件導入 Unity 裏,由於 Unity 會在打包項目時會從新壓縮。因此不須要先壓縮再導入Unity,這隻會下降音效質量。
強制音效用單聲道
只有少數的手機裝置真的有立體聲喇叭,而將音效強制設定爲單聲道能讓內存的消耗減半。就算遊戲會輸出部份的立體聲,有些單聲道像是 UI 音效仍是能夠開啓這個選項。
下降音頻的取樣
調低取樣能進一步下降內存消耗和最終項目的大小,能夠和音效設計師協調找出最小最能接受的音源質量。參考SetCompressionBitrate。