細談unity資源管理的設計

zblade發表於2019-06-26

一、概要

本文主要說說Unity是如何管理的,基於何種方式,基於這種管理方式,又該如何規劃資源管理,以及構建bundle,是後面需要詳細討論的。

二、Unity的資源管理方式

2.1 資源分類

unity專案中的資源,大體上可以分為外部匯入資源和內部生成資源兩種型別。
外部匯入資源: 美術生成的大部分資源,都是外部帶入資源,模型,貼圖,UI用圖,基本是美術工具生成後,匯入到工程中的。
內部生成資源: 部分美術生成資源,例如材質,shader,特效,場景等,屬於基於Unity引擎來製作生成的,此外各種prefab(UI/角色等),以及程式碼指令碼(c#為主),也屬於Unity的內部生成資源。

2.2 資源的儲存方式

在資源匯入到unity工程後,會以各種方式進行轉換儲存,主要有以下幾種:

2.2.1 指令碼類資源

對於工程中的指令碼類資源,主要分為plugin和非plugin兩類。

  • plugin類:在plugin中引用的dll, 屬於自己生成相關的dll,在最終構建遊戲包的時候,被打入到相關遊戲包中:      
  • 非plugin類:unity會構建成4個基本的dll, 構建的順序為:
    • Assembly-CSharp-firstpass: standard assets/Pro standard assets/plugins 中的指令碼
    • Assembly-CSharp-Editor-firstpass: editor scripts in standard assets/Pro standard assets/plugins 這個dll不會被打入到遊戲包中,屬於編輯器下特有的dll
    • Assembly-CSharp: all other scripts that not inside editor 主體遊戲邏輯的dll
    • Assembly-CSharp-Editor: all remaing scripts inside editor 這個dll也不會被打入到遊戲包中,編輯器中特有的dll

所有最終構建到遊戲包中的dll,主要分為:

  • Assembly-CSharp.dll/Assembly-CSharp-firstpass.dll 這2個主要遊戲邏輯dll
  • 引擎dll和外掛引用的dll

2.2.2 美術類資源

美術類資源,分為外部匯入和內部生成兩個大類

  • 外部匯入類: 場景/模型/貼圖 都可以外部匯入
    • 繼承自AssetPostprocesser後,可以對匯入的貼圖,材質,模型,場景,均執行相關的修改
  • 內部生成類: shader/材質/prefab/場景 均可以內部生成美術資源的貼圖資源和特效資源,屬於重點關注物件,後面會細談這幾個資源的管理
    • 修改操作同上

2.2.3 meta檔案

工程資源劃分好後,如何對這些資源進行管理? 不同的引擎有不同的管理方式,那麼unity中是如何管理的?
這兒管理分為2個步驟:序列化和meta檔案的生成

2.2.3.1 unity的序列化

工程中的資源,要儲存到本地磁碟,那麼就會通過引擎進行一步序列化的操作,序列化的實質,就是將資源物件按照一定的順序轉換成二進位制檔案。

2.2.3.2 meta檔案的生成

在完成序列化後,unity會對應的為該檔案生成一份meta檔案,這份meta檔案會跟隨該檔案一直存在,如果刪除該資原始檔,其對應的meta檔案也會被引擎自動刪除。
meta檔案的主要構成:

  • 檔案的guid: 這個檔案的全工程中的唯一索引id,基於該id,可以對應的查詢到該檔案。guid的生成本質,就是基於檔案的路徑來進行轉換生成的,同理,如果多個工程合併的時候出現guid衝突,可以自己重新生成一份guid,相關連結: https://gist.github.com/ZimM-LostPolygon/7e2f8a3e5a1be183ac19

  • 檔案的匯入設定:

    • 對於一般的檔案,匯入設定都比較簡單指令碼類叫MonoImporter, 資源類叫NativeFormatImporter
    • 貼圖屬於需要重點關注的型別,其匯入型別叫TextureImporter,裡面詳細的列出對該貼圖的各種壓縮格式,mipmaps, 型別,uv,貼圖大小等等詳細的設定資訊

2.2.4 基於meta檔案和序列化的資源管理

除了meta檔案的guid,unity還會為每個資源生成一份檔案id,也就是fileID, 不過現在fileID已經不再保留在meta檔案中了,保留到檔案的序列化檔案中了,對於該資源,還會有一份localID, 這個localID, 對應的就是在一個資源中包含多個子資源的時候,定位每個子資源所用:  

那麼序列化是如何與guid/fileID關聯的?
在unity工程內部,如果給資源新增其他資源的引用,例如加一個指令碼,拖拽一個外部引用,那麼就會觸發一次序列化操作,序列化操作的時候,就會將引用的資源的fileID和guid都序列化下來,這樣在反序列化的時候,就會基於fileID和guid來反向找到依賴的資源,從而載入進來。   

這個過程,在Unity中,就是一個裝載的過程,多說一句,如果一個資源依賴的其他資源越多,那麼這個裝載過程就會越耗時,所以在開啟一個很大的UI的時候,有一部分的時間是消耗在裝載UI上各個元件上的。

三、總結

基於前文,可以對整個unity的資源管理有一個初步的認識,基於meta檔案和序列化操作,可以管理工程中的資源,同時也能管理好各個資源的互相引用,那麼基於這樣的設計,在構建bundle的時候,是可以進行相關的設計和實現的。

相關文章