游戲中通常有大量資源,如網格、材質、紋理、動畫、着色器程序和音樂等,游戲引擎作為做游戲的工具,自然要提供良好的資源管理,讓游戲開發者用最簡單的方式使用資源。游戲引擎的資源管理包括兩大部分:離線資源管理和運行時資源管理。本文僅對前者進行簡要介紹,並結合Unity3D和OGRE進行分析。
資源創作與導出
游戲中的資源由各種數字內容創作工具(DCC, digital content creation)進行創作,如:
- 三維模型:3ds Max,Maya等;
- 紋理:Photoshop等;
- 音樂:Sound Forge等;
- ………………
DCC往往支持多種導出格式,如:
- 3ds Max:3DS、AI、DDF、DEM、DWG、DXF™、HTR、FBX、IAM、IGES、IPT、LP、LS、MTL、OBJ等;
- Photoshop:PSD、TIFF、EPS、PCX、GIF、JPEG、PNG、PICT、TGA等;
- ………………
游戲引擎一般會支持指定DDC的部分導出格式,例如Unity3D支持3ds Max導出的FBX格式;或者針對特定資源創作工具編寫導出插件,例如OGRE有多種三維建模軟件的導出插件。雖然基本上所有DCC都支持多種導出格式,但是很多情況下這些格式都不適合游戲引擎,因為
- 導出的內容過於復雜,游戲中只用到其部分數據,而游戲往往對性能的要求比較苛刻,所以需要去除冗余數據;
- 許多DCC導出的格式讀取比較慢,而且還有一些是封閉格式導致引擎無法讀取。
因此,在DCC導出資源后,需要引擎進一步處理,將資源轉換為引擎的內部格式,這種處理被稱作Asset Conditioning Pipeling。使用Unity3D的童鞋應該會發現,每次導入資源的時候都要讀條,就是在進行Asset Conditioning Pipeling;OGRE在這方面的支持不夠完善,這部分工作由自定義的導出插件完成。
資源的“編譯”與“鏈接”
由於導出的資源存在一些問題,需要進行一定的轉換,這個轉換被稱作Asset Conditioning Pipeling,包括2個步驟:
- 資源“編譯”
讀取單個資源的數據,將其轉換為游戲中可以直接使用的格式(使用效率最高或較高的格式),例如重新對Mesh的頂點進行排序,或使用BC5等壓縮算法對紋理進行壓縮。這個過程與C語言的編譯有些類似,因此取名為“編譯”。當然,如果導出的資源可以直接使用,那么可以跳過這一步。
- 資源“鏈接”
在游戲中,許多資源並不是單獨使用的,例如三維模型,它引用的材質和紋理是單獨存在的資源。在上一步中,引擎對單個資源進行“編譯”,將其轉換為可以直接在游戲中使用的格式;這個步驟將所有的資源進行“鏈接”,使得游戲在運行時可以找到每個資源所依賴的所有資源,例如三維模型可以正確的找到其需要的材質和紋理。這個過程與C語言的鏈接有些類似,因此取名為“鏈接”。當然,如果導出的資源可以直接使用,那么也可以跳過這一步。
Unity3D對這部分提供了比較完善的支持,因此只需要導出引擎所支持的標准資源,並放入Assets文件夾,引擎會對其進行“編譯”和“鏈接”,結果就在Library文件夾中(里面亂七八糟的,雖然我們看不懂,但是Unity3D很喜歡);OGRE沒有提供專門的Asset Conditioning Pipeling工具,因此所有操作都在資源的導出插件中完成,沒有進行單獨的“編譯”和“鏈接”。
資源管理數據庫
在資源通過Asset Conditioning Pipeline之前,引擎需要存儲處理該資源的方式,一般使用metadata(元數據)來描述,例如指定某個紋理應該是以何種方式壓縮。引擎通過資源數據庫來管理metadata,資源數據庫既可以簡單的使用XML文件進行描述,也可以使用MySQL等數據庫。游戲開發者通過引擎提供的接口實現資源的重新配置,例如在Unity3D編輯器中可以修改Mesh的壓縮方式,選擇是否優化Mesh等。
游戲引擎的資源數據庫一般要提供如下功能:
- 創建和刪除資源;
- 查看和修改現有資源;
- 將資源移動到其他路徑;
- 支持資源的相互引用,並且在被引用資源移動路徑后,保證引用有效;
- 提供多種便捷的查找資源的方式。
使用Unity3D的童鞋可以發現,Unity3D提供了比較完善的資源管理的功能,使用起來比較輕松。
資源讀取(運行時)
在開發過程中,所有原始資源以單個文件形式進行保存,以方便修改,但是在游戲運行讀取資源的時候,為了加快讀取速度,一般會將資源打包成一個或多個文件。打包的原因很簡單,從硬盤中讀取文件的時間中,主要由三部分組成:
- 硬盤尋道時間;
- 打開文件的時間;
- 讀取文件的時間。
最后一項是不可能改變了,除非使用速度更快的存儲介質;但是將多個文件打包成一個文件,可以縮短前面兩項的時間。Unity3D在發布游戲的時候,會將資源進行打包;OGRE沒有自定義打包資源的方式,一般打包為一個或多個ZIP文件,或不打包資源。
實例分析
Unity3D
拷貝Unity3D工程的時候,一定要拷貝“Assets”、“Library”和“ProjectSettings”文件夾。資源都在“Assets”,設置都在“ProjectSettings”,“Library”是來打醬油的?非也!如果不拷貝“Library”,打開工程以后你一定會大吃一驚,之前的設置全沒了?!而且場景文件里的東西也是亂成一團!結合上文,則很容易理解這種詭異的現象,明白為什么少不了這個“打醬油”的“Library”。
將資源放入“Assets”文件夾,切回Unity3D,則進入Importing Assets狀態(進行Asset Conditioning Pipelining),如下圖

導入資源
在這個步驟中,Unity3D針對所有的資源生成metadata,並進行“編譯”、“鏈接”,轉換為游戲可以直接使用的資源。轉換前的資源保存在“Assets”中,轉換后的資源保存在“Library”中,所有的資源在Inspector面板中可以修改metadata的數據,如下圖

“Library”文件夾

Inspector
如果使用SVN等版本控制器,需要同步所有資源及其metadata。打開Edit->Project Settings->Editor,將Mode修改為“Meta Files”(默認“Disabled”),如下圖

選擇“Meta Files”
Mode修改為“Meta Files”后,回到資源文件夾,會發現每個資源都多了***.meta文件,如下圖,而這些.meta文件保存了這些資源將如何被Asset Conditioning Pipeline處理。

帶metadata的資源文件
現在Assets文件夾中不僅有所有的資源,而且還有對應的metadata,“Library”徹底打醬油了,此時在拷貝工程或使用SVN同步工程時才可以忽略“Library”文件夾。
在發布的游戲中,資源文件如下圖所示。可以發現,Unity3D對資源進行了打包,以減少資源載入時間。

發布后的游戲資源
總的來說,從導入資源,生成metadata,“編譯”、“鏈接”資源,再到發布游戲時打包資源,Unity3D都封裝好了,以最簡單的方式提供給我們使用,極大的提高了游戲開發者的工作效率。雖然可能第一次在用的時候只是感覺Unity3D用的比較簡單,但它確實在背后做了很多工作,只是我們沒注意而已。
OGRE
OGRE在這方面的支持與Unity3D相比差距比較大,只提供了資源的導出插件;發布的游戲中,可以使用ZIP對游戲資源進行打包,未提供自定義資源打包方式。當然,總體來說,它是一個相當不錯的圖形引擎,最重要的一點是,它是開源的。
