Milo的遊戲開發
從頭開始思考遊戲的資料管理系統(二)
上回談及一些遊戲資料管理的初部分析,但有些思緒還沒有整理好,寫得頗亂。今次就直接談我在幾個月前設計的Mil Universe Database (MUD),從中再闡述當中的一些想法。
基本的資料流程

首先,一個項目中的所有引擎會使用的資料,都放進一個完整的資料庫裡。現時我的設計一個資料庫會儲存成一個 .mud檔案。
外部檔案可以滙入資料庫,也可以滙出。但滙出的資料會失去一些資訊(如稍後說的依存關係)。
資料庫最後會轉換為平台特定的格式,如轉換Endianness、轉換模型和紋理格式、轉換XML到二進制格式、編譯腳本等等。這步驟的主要目的是加快遊戲讀資料的速度。此外,也可以把關卡或人物的資料(如三維模型、紋理、動畫等)包裝成一個資料塊(data chunk),優點是進一步加快了讀資料的速度(尤其是光碟,因為seeking慢),缺點是一筆資料可能出現在多個資料塊中,增加了遊戲的容量,而且可能會讀到已載入的資料。
如果多人參與同一項目,該資料庫會分為中央和本地的資料庫,透過版本控制同步及提交更新。這裡描述的是一個可離線編輯的版本控制系統,我也和伙伴討論過其他方式,可見使用Database Server+Source Control Server构建游戏开发用数据文件的可行性分析。
功能需求
構想MUD 時考慮了以下的需求。
完整單一資料庫
上回說到一個遊戲項目會有數萬以上筆資料。如果每筆資料以獨立檔案儲存,會產生很多問題。我覺得缺乏完整性 (Integrity)是最大的問題。所以MUD是以單一的資料庫儲(.mud檔案)存整個項目的資料。
Key
使用整數作為每筆資料在永續時的Identifier,稱為 Key。Key只是系統才知道的,製作人員應該從來不需要知道這概念。
層階式檔案系統
每筆資料會有路徑和檔案名稱,但這只是給使用者「看」而已,遊戲引擎始終是使用Key作為Unique Identifier。資料庫轉換成平台格式時,這些路徑檔名會被忽略,不存在於遊戲的執行版本。
依存關係
資料和資料間的依存關係會記綠下來。如一個三維模使用數個材質;每個材質又使用數個紋理。當一筆資料被刪掉時,可提醒使用者該資料被那些資料使用,如果確定刪去,也會通知其他資料刪去那些使用參考。
腳本也是用Key去挷定資料。例如一個腳本會在執行期,在某些情況下改變它的遊戲物件的三維模型,那麼該腳本會定義它需要一個三維模型的(成員)變數。關卡設計師會把腳本挷定在一個遊戲物件上,並設定它需要的三維模型。這遊戲物件永續時儲存了三維模型的Key,而在執行期腳本則拿到了三維模型的物件(指針)。這可以解決把資料(如路徑)直接寫在腳本所產生的問題。
此外,依存關係也可以找出及清除一些孤立的資料(沒有其他資料會依存的資料)。當然,要做到這一點,還要定義一個(或一些)根節點。
版本控制
遊戲的資料通常由很多人參與製作,版本的控制是十分重要的。我未詳細考慮怎樣實現MUD的版本控制。簡單的方案是使用SVN之類的檔案版本控制軟件的API,把Key轉為檔案去存取。但仍要考慮資料以外的東西怎麼作版本處理(檔名、依存關係等等)。
其他擴展功能
- 資產管理(Asset Management): 除了儲存遊戲編輯工具和遊戲引擎會直接使用的檔案,亦儲存來源檔 (.max、.psd ),並有workflow自動轉換這些檔案,例如紋理的大小和mip-map設定。
- 壓縮: 加快檔案的讀寫、減少磁碟使用空間。
- 加密: 加強安全性 (開發時期的泄漏、出版後被反組譯等等)
Schema設計
我之前設計的第一個Mud版本應該是以C++直接實作,但schema用一般database畫出來可能比較容易明白:

最重要的是Key table,它記錄每個key所指向的資料的大小、類型、和儲存在資料庫中的offset。
File、Folder和Dependency都是制作期的資料庫才有的,這些 tables在最終運行版的資料庫會被刪去。
API 設計
以下是Mud API的第一個版本,當中示有 Retail的函數是遊戲正式版需要的函數:
class MudFile { public: MudFile(char *mudFileFilename); // Retail // Mud file manipulation bool Create(); bool Open(); // Retail bool Close(); // Retail bool Check(); bool Compact(); // Transaction bool BeginTransaction(); bool Commit(); bool Rollback(); // Read/Write bool OpenReadFile(Key key); // Retail bool OpenWriteFile(Key key); bool CloseFile(); // Retail uint32_t ReadFile(void *buffer, uint32_t maxSize); // Retail uint32_t WriteFile(void *buffer, uint32_t size); // File manipulations Key CreateFile(FolderID folderID, char *filename, FileType type); bool DeleteFile(Key key); bool RenameFile(Key key, char *filename); bool MoveFile(Key key, FolderID folderID); // File information char *GetFilename(Key key); uint32_t GetFileSize(Key key); // Retail FileType GetFileType(); // Retail FolderID GetFileFolder(Key key); // Folder manipulations FolderID CreateFolder(FolderID parentFolderID, char *folderName); bool DeleteFolder(FolderID folderID); bool RenameFolder(FolderID folderID, char *folderName); bool MoveFolder(FolderID folderID, FolderID parentFolderID); // Folder information char *GetFolderName(FolderID folderID); FolderID GetFolderParent(FolderID folderID); // Path string GetPath(Key key); Key GetKeyByPath(const string& path); // Folder/File Traversal FolderID GetFirstChildFolder(FolderID folderID); FolderID GetNextSiblingFolder(FolderID folderID); Key GetFirstFileInFolder(FolderID folderID); Key GetNextFileInFolder(Key key); // Dependency bool AddDependency(Key source, Key target); bool RemoveDependency(Key source, Key target); KeyList GetSources(Key target); KeyList GetTargets(Key source); };
我把這組API盡量設計得簡單,減少所需要的類別(如File、Folder類別),使C# (或其他語言)的Binding容易實作。在Retail版中,只需要少量函數,實作多個平台的版本也變得容易。
我原來的設計裡還有 Transaction 的考慮,希望可以加強database的integrity。例如程式在運作中途異常結束,database的內容可以維持consistency (不會有只寫了一半的資料或資料組)。
後記
這一篇文章其實只談及一個解決方案,並沒有很仔細的分析每個決定,及討論其他方案。如果有寫得不太清楚,或有任何意見,歡迎留言討論。
- Comments: 1
- Trackbacks: 0
從頭開始思考遊戲的資料管理系統(一)
和一般應用軟件有點不同,大部份遊戲軟件都需要使用大量的遊戲資料 (Game Data)──或稱為資源 (Resource)、資產(Game Asset, 但通常Asset包括資料的原始格式, 不是最終運行遊戲所需的資料)。在製作遊戲時,如何管理這些資料是一個非常重要的問題。曾經看過和使用過不同的方案,現在歸回原點,分析基本的需求,隨筆記錄我選的方案的思路。
遊戲資料管理的重要性
如果從遊戲軟件的產出 (deliverables) 來分析,一個遊戲軟件可以分為三部份:
遊戲引擎: 比較固定的、和遊戲性無直接關係的程式
遊戲唯讀資料: 腳本、圖像、音效、關卡、影像
遊戲讀寫資料: 遊戲存檔、遊戲設定、玩家自製內容
從現今的遊戲實際容量來看,遊戲引擎可能佔1~10MB、遊戲讀寫資料10KB~10MB,其餘以GB為單位的全是唯讀資料。以開發人員來計算,開發引擎可能是數人,但製作那些唯讀資料的隊伍是以百計的,主要是遊戲性程式設計師、人物美工、場境美工、關卡設計師等等。
本文主要談遊戲唯讀資料,所以以下會「資料」或「遊戲資料」皆指「遊戲唯讀資料」。
遊戲資料可以有幾多筆?
接著我隨便估計一個「小」遊戲需要的資料筆數(筆數在下節定義)
20 關卡 x (200關卡貼圖 + 100關卡模型 + 200遊戲物件) = 10000
40 人物 x (3人物貼圖 + 2人物模型 + 20人物動畫) = 1000
200視覺效果x (5效果貼圖 + 5動畫) = 1000
20使用者介面x 25貼圖 = 500
(100物件腳本 + 80人物腳本 + 20使用者介面腳本) x 5原始代碼檔案 = 1000
180音效 + 20音樂 =200
總和 = 13,700
以這個推算遊戲的資料筆數數量級一般在10^4 至 10^6。我覺得極限只是會到10^7,因為大量資料是模型、貼圖、動畫等,平均值不會少於10KB,而10^7 x 10KB 已經是 10GB。
遊戲資料的概念分析
我心目中的遊戲資料是有以下特點
- 唯一性 (Uniqueness): 每筆資料有它唯一的Identifier,透過一個identifier可以讀取一筆資料。
- 不可分割 (Atomic): 當把一些資料分割成多筆資料是沒意義的,就算是一筆資料。例如假設一張貼圖不會讀取、使用其中一部份,則視為一筆資料。
- 依存關係 (Dependency): 一筆資料可能會靠identifiers引用其他資料。這和上不可分割屬性也有關係,因為是用identifier依存某一個資料,而不是該資料內的一部份。我未想到會有循環的依存關係,暫時把依存關係當作一個 Directed Acyclic Graph (DAG)。
一般檔案系統的檔案和這裡的資料有點不同。檔案的路徑可以視為Identifier,但很多檔案的內容是可以再分割的,而且沒有顯性(explicit)的依存關係。
選擇Identifier
我看過和想到的資料的Identifier可以是:
- 路徑 (path): 例如 Texture/wall.jpg
- URL: 例如 Texture/wall.jpg、http://www.mysite.com/news.jpg
- 整數: 例如 0×54AF4C58
- GUID: 例如 {3F2504E0-4F89-11D3-9A0C-0305E82C3301}
路徑
檔案系統的路徑可能是最直覺的資料Identifier。我以前做過的引擎,和很多商用引擎也會使用檔案和路徑這個表達方式。路徑通常是相對於某一個目錄、或一個壓縮檔(例如 id 的引擎會把檔案壓縮在一個zip檔裡)。
路徑的好處是和我們日常用的操作系統管理檔案的方式一樣。層階式 (hierarchical)的目錄結構讓使用者可以自行分類管理,你亦可以歷遍(traverse)目錄結構,例如讀取某一目錄的*.lua。它實作簡單,因為操作系統已提供所需功能。也可以使用一些現存的版本管理工具去直接管理這些資料,如SVN、Perforce等。
路徑的壞處包括: 大小寫問題、多國文字問題、儲存效率差、運行效率差。前二者太概都容易明白,不再詳述。儲存效率差是指用字串去記錄每個identifier,包括引用時的identifier都會花費不少空間,而且路徑(不單是檔案名)的長度可以很長(例如可能要256 位元組)。而運行效率差是因為比較兩個路徑慢,計算一個路徑的hash code (例如用路徑identifier做 hash_map或hash_set 的key) 也是很慢而且不是常數速度。在遊戲運行期,這些路徑文字資訊是冗餘的,因為玩家不會看到。
URL
URL 算是路徑的延伸。這延伸的好處是它是一個標準(不會有平台相關、大小寫、多國語言等問題),而且有些XML裡也會用URL作為引用的identifier。另外,可以選擇性支持不同的協定 (protocol),例如透過http存取互聯網上的資源。其他壞處和路徑差不多。
整數
整數是最簡單的identifier。通常關聯式資料庫(relational database)的表(table)都以一個整數欄作為列的primary key。相對前兩種identifier,整數的好處是儲存量小而速度快。
整數identifier的缺點是,整數對使用者而言沒有任何意義,也沒有層階式的管理系統。
另外,多少位元才足夠呢? 從之前的估計,10^7筆資料用32-bit就足夠了。用另一個角度想,如果一個5年的項目有100個成員會添加資料,一周工作7天的話平均每人每日可以增加23534筆資料,嗯……應該足夠吧,除非資料經常大量刪去又創建資料(每次都產生新的identifier)。要澈底杜絕Identifier不夠用,可以重用舊的刪去了的Identifier,或是把現有的所有Identifier重新編號。
整數identifier在多人同時建立資料的時候,還要考慮如何令identifier不重覆。解決辦法之一是連線到一個identifier產生的伺服程式。
GUID
最後,GUID的好處是確保在不連線下,每人也可以得到不會重覆的identifier。缺點是GUID的大小為128-bit,是32-bit的4倍。
之後
這幾個簡單的段落已花了我一整個晚上,我想繼續寫有關這些遊戲資料的使用流程,並最後闡述現在做的引擎在這方面的設計。還是那一句,希望多些交流指導。
- Comments: 7
- Trackbacks: 0
《程序員修煉之道》、《代碼之美》、《Real-time Rendering 3rd Edition》、《Physical-based Rendering》
- 2009-03-04 (三)
- 閱讀
新年過後,Mil的開發進度有點慢,花了斷斷續續一個月才完成了一個簡單的 translate gizmo。要長期維持熱情真的不容易。由於沒甚麼Mil的進展可以看,今天也未想到做那個 story,就在此和大家分享這幾個月看過的書。
程序員修煉之道 (英文注釋版)
The Pragmatic Programmer: From Journeyman to Master

我對這書本來沒有很大的期望,而且它的書齡比較大,只是當作休閒讀物,但閱後喜出望外。除了有不少有用精闢的題示,還真的有不少能激發思考的寓言。分享幾個和程序員心理有關的例子,一個提示為
Tip 4: Don’t Live with Broken Windows
說的不是M記的Windows (笑)。故事是說一些研究人員發現,一個漂亮整潔城區如何開始衰落──當一個窗子破了沒修,就會令人覺得業主不關心那大廈,其他人就開始亂拋垃圾、塗鴉,不斷惡性循環,最終變成腐敗地區。
在我的過去,也有不少類似的項目。有時候不是時間的問題,而是心理上的問題。面對寫得不好的東西,沒心要把它弄好,最終只會是一些被廢棄的代碼。又或是,看到一些小bug沒去查,最後要花更多的時間精神去修正,或又是把它放棄。
每看到程序中有問題的地方,就不要容忍。問題可以是設計上的、編程上的。時刻要想著 refactoring。 不要把系統惡化。
另一個提示
Tip 30: You Can’t Write Perfect Software
這個也許是一個顯淺的提示,對我來說郤是一個反省的機會。從來,我希望可以寫出好的程式、好的代碼,希望可以追求完美。但這是不實際的。從來沒有完美的軟件,將來也不會有。軟件內不完美,使用軟件的人或軟件也不完美。要接受這個現實,並反過來令程式在不完美下完成工作。編寫 defensive coding、unit testing。不要為了避免有bug而寫一些「不對的保護」(例如函式內參數不對就直接返回),如果是有問題的,就讓它 crash (或assert等) 並找出問題來源,比匿藏那些問題好。
Beautiful Code: Leading Programmers Explain How They Think
代碼之美

相反,這本原來比較有期望的著作,閱後(沒有全部讀完)有點失望。
有些文章是有些趣味,有些覺得非常沉悶。總體來說,看不到作者們對「美」的看法。一些簡短程式做到比較複雜的功能 (例如 quick sort、regular expression),看上去是不錯的,雖然也不知道簡單是否是美。一些大系統 (例如 ERP…… 囧) 完全不知道他們從那個角度看到它的「美」。
或許,
Beauty is in the eye of the beholder
代碼需然用文字寫成,但是否和詩詞一樣,應用、或可用「美」這個形容詞去度衡量,是一個問題。
買這本書的人或許要三思。
Real-Time Rendering 3rd Edition

毫無疑問,這是一本非常好的書。1027頁、1416個參考文獻、全彩印刷、幾乎沒有廢話和無用插圖(嗯……第三版是有一些比較大的遊戲截圖)、非常全面的內容。開賣時 amazon還打折比買第二版還平宜,是超值的珍藏。第一次擁有這本經典 (第一版在大學圖書館借過,第二版在以前工作上採購過),第一次由頭到尾去閱讀,每個章節都看到自己不懂的新事物。第三版新加入的內容也對我有吸引力。雖然看過一次,但一次絕對不夠,有時間會再讀,再加深理解。
Physically Based Rendering

我在大學沒讀過計算機圖形學、沒寫過 Offline Renderer,所以想多學一些這方面的知識。而另一方面,也憧憬未來計算機圖形的硬件發展,Real-time Ray-tracing、Radiosity 也許會變成主流。這本書提供了理論基楚,和一個 Offline Renderer 的實作 (pbrt),是少有的理論與實際並重的書。
嘗試從頭到尾看一篇,但是後面關於 Monte Carlo Integration 和 Light Transport Equation 對我來說是很難。有時間會再看。
這本書的一個缺點是異常重 (5.5磅 = 2.5 公斤),在床上看腹部會感到很大「壓力」;相對的優點是可以訓練手部肌肉。
閱讀計劃
由於看過《程序員修煉之道 (英文注釋版)》,想繼續看幾本類似的原文書,包括 Kent Beck 的注釋版:
- Implementation Patterns
- Test-Driven Development by Example
注釋版是挻方便的,英文生字也不用查字典。
最近還發現剛剛這兩本 Morgan Kaufman 的大陸版英文原文版:
- 3D Game Engine Design 2nd Edition
- The Art of Multiprocessor Programming
第一本是剛2009年出版的,現在還斷貨。這書值得參考,尤其是數學部份。
第二本的原書是上年出版的,大陸版也是上年出版。這新書一直想讀,因為自己在這方面比較弱,面對 multi-core 的年代,一定要多多學習。
英文版除了原汁原味,還可以溫習英語,而且有些大陸版的原文書的人民幣價格比原書美金價格還低。真好。
- Comments: 0
- Trackbacks: 0
Freetype2向量文字渲染
- 2009-01-20 (二)
- 圖像編程
上回使用Freetype2的光柵化(Rasterization)功能把文字渲染到 Texture上,再把 Texture 渲染到螢幕上。除了這個方法外,前文也提及可以把字型以向量方式渲染。在朋友的慫恿下,加上未有這方面的經驗,便花了兩三天去實作這個功能。雖然這個功能在遊戲中完全不重要,但實作這個的難度比預期高,也沒找到類似的參考,而且需要用許多計算幾何(Computational Geometry) 的演算法,對我來說,好像是一個學習和練習的功課。我嘗試把實作的過程記錄下來,和大家交流。
- Comments: 3
- Trackbacks: 0
Freetype2 文字渲染
- 2009-01-16 (五)
- 圖像編程
Freetype2 是一個開源的文字渲染程序庫,支持多種向量和點陣字型格式。以前的項目用過這程序庫,不過不是我親手整合。以前的項目有很多不同的重載函數去提供各樣文字渲染功能。今個星期花了三天整合,花了不少時間想,怎麼可以最有彈性、又最簡單呢?
- Comments: 0
- Trackbacks: 0
平台遊戲的遊戲性實驗
- 2009-01-12 (一)
- 腳本編程
經歷接近一年,這是本 Blog 第一個可「玩」的小測試。測試程式(包括 Lua 源程序)可在本文章末下載。
由於 MilStudio 等著 MUD 模組才好繼續,就先來做一個平台遊戲的遊戲性實驗,過程非常有趣 (可能是因為很多個月裡只是在做引擎和工具),所以這星期一口氣完成了 10 個 stories。
實驗內容
- 控制角色,做出走路和跳躍兩個動作。
- 繞著角色迴轉的攝影機,角度會按主角移動而自動迴轉,玩家也可以改變角度。
- 加入一些箱子,可與角色作物理互動 (角色能推動箱子,箱子也能影響角色)。
- 加入移動平台,它們會在兩點中循環移動。角色站在平台上會受平台的慣性影響。例如角色站在水平均速移動的平台向上跳,他掉下來時在平台的位置應該和跳的時候一樣。
- Comments: 4
- Trackbacks: 0
2008年回顧和展望
- 2008-12-31 (三)
- 遊戲編程
迎接家人的來臨後,慢慢適應了新生活。每天還是找到一點時間,看書、寫引擎、和看動畫。很久沒更新這 Blog,就先說說這個月的引擎進展、今年的工作、和明年的展望吧。
本月引擎進展
自從十月中旬開始使用敏捷方法,45 個 stories 中完成了 26 個,平均每個 story 花上了一、兩個晚上。以下簡介一下完成的部份。
MilStudio
我們花了比較多的時間在 MilStudio 這個工具上。雖然它目前還是非常簡陋,但進展還算不錯。
- Script Editor: 由 Textbox 作為文字編輯器升級至 ScintillaNET,支持 Lua syntax highlighting、搜尋、取代、跳行等等。ScintillaNET 還支持一些將來做 IDE 很有用的功能,例如在 debug 時加入箭頭和斷點等符號。
- Game Window: 渲染遊戲內容。現在加入了簡單的 Camera Navigation 和 Picking。
- Entity Window: 以 TreeView 顯示 Entity 層階,也可以選取 Entity。因為之前在物件刪除時會 crash,Refactor 了一次,使 Mil 的資料和 MilStudio 的顯示同步。
- Property Window: 顯示和修改目前選取的 Entity 的屬性。
目前可以用 MilStudio 編寫一些簡單的測試,但由於仍欠缺 World 的 Persistency,MilStudio 並沒有實際創建和編輯Entity 的能力。
- Comments: 3
- Trackbacks: 0
協作,敏捷,繼續做引擎
- 2008-11-18 (二)
- 遊戲編程
距離上一篇 Blog 已經是兩個半月了。光陰似箭,兒子也出生了,引擎的開發進度還是很慢。
希望引擎不用等到兒子接手才能完成,回來上海後,最近有了一些新進展。
首先,決定不再獨自閉門做車,找了同事 xlyao 一齊在工餘時間開發。很多獨自煩惱想不到解決科案 (通常是太多科案選不來),兩個人經過討論後就較容易得出結論。
第二,採用所謂敏捷軟件開發方法 (Agile Software Development)。我對 Agile 也許還是一知半解,希望逐步能掌握箇中真諦。
現時的開發過程包括以下數項。
User Story
一個 user story 是一個由 user 提出的明確要求。這些 user story 是要很細小及可以簡單驗証的,例如「使用者可以在地圖編輯器點選一個物件,把它複製。」
我們利用 Google Docs 的 Spreadsheet 輸入 user stories。這些 stories 沒有指明由誰來做,誰喜歡做那個就拿來做,記下開始及完成日期。
User story 的好處是軟件的功能按實際所需而增加,而不是在項目開始時花很多時間寫一份軟件需求規格。因為每個 User story 都比較小,軟件能不停有新的產出 (deliverable),也能讓使用者驗証是否合乎他的要求。傳統的做法有時可能花幾個月時間在一個需求上,但後來又發現和實際所需有所分別。另一個好處是,程序員可能用幾小時或幾天時間便可以完成一個 story,不用預先考慮太多將來未知的需求,心理上也能得到點成就感。不過也要有打算,未來會因為新的 story 而要把舊的代碼重構 (Refactor)。
審核
每個 User Story 完成後,現時是直接 commit 進 SVN 伺服器。我設置了 svnnotify 程序,當有 commit 時會發電郵給所有人,內容包括 log 和 diff。我們需要審核代碼,並應該測試是否符合 story 的要求。
溝通
敏捷很重視溝通。撰寫 Story 可能是一個人提出的,但應該要和其他人解釋。Story 不會寫的很深入 (和傳統的軟件規格有分別),要討論來得知詳細的需求,和如何把它實作。
未來
敏捷方法還包括很多 practice,我們暫時未正式採用,或許將來會慢慢加入吧,例如:
- Poker Planning: 透過各自估計 story size point (規模點數),和別人比較和討論後,決定 story 的 size point。
- Sprint planning: 每個 sprint (時間單位,例如一週) ,按 story 的優先次序、依賴性及 point 預算 (以之前的 Sprint 能做多少 point 和這個 sprint 的人手時間等決定),去決定做那些 stories。
- Stand up meeting: 每天工作開始時,所有隊員站立開會,討論上一天的工作情況及今天的計劃。這個應該沒可能了……
- Sprint review: 每個 sprint 結束後討論 sprint 做得好與壞的地方。
雖然開始協作和敏捷方法只有數天,但感覺上項目有了新的動力,希望能在很短的未來能不斷有產出,和大家分享。
P.S. 我把兒子起了英文名字── Lua,真的寫了在出身證名文件裡……
- Comments: 3
- Trackbacks: 0
開始實作引擎的基本類別
話說之前想做 Collada 滙入,便最基本要有一個內部存放 Collada 滙入後的資料。這個「雙休日」(內地常用語) 就留在家中乖乖寫程式……寫不出的時候也看了十幾集動畫。
架構上參考了之前看過的 Unity,採用 Component 型式。目前實現的幾個類別的關係如下圖:
採用 Component 架構的一個好處是,減少了傳統 Scene Graph 的類別繼承和節點 (node) 數目。一個實體 (entity, 有些引擎稱為 Game Object) 可以有 Mesh 元件,也可以同時加入腳本、碰撞物件等元件。
實作過程中出現許多問題,和大家 (及將來的自己) 分享一下。
- Comments: 2
- Trackbacks: 0
希望在家繼續做遊戲,首先還是做 COLLADA 吧
說點近況。自從四月回港參加好友的婚禮,帶了台 Xbox360 回上海後,便花了許多時間「研究」遊戲,包括我公司的幾個作品,之後也「研究」Wii 的各種遊戲。家人回港後獨自一人,還看了蠻多的動畫和最近的奧運。之前在家中做的項目便擱置了將近半年……雖然也不是完全沉醉於「研究遊戲」和其他娛樂上,書和文獻也有看一些,但還是覺得生活應該得更充實一點。這幾天又再想繼續之前的項目。
第一件發現的是,我的記憶能力真的很有限。過了五個月,幾乎完全忘記了之前的想法、進度等等。全靠閱讀這個 Blog 才知道五個月前的 Milo 在想甚麼。「外置記憶體」真是很重要,而且可以用來認識過去的自己。不知道還能否找到十年前在網上發表的日記,看看當時頗年少氣盛的自己。
讓 COLLADA 作為新起點
之前的項目主要做了非常基楚的混合語言、跨平台圖像及工具的嘗試。本來想繼續做一點輸入及物理,以完成整個遊戲循環,做到一點互動的機制。但是,對比較喜歡電腦圖像編程的我來說,始終敵不過引誘,想載入一些比較好看的3D模型,並且做一些實驗。因此,暫時想先做載入3D模型的部份。
要載入3D模型,COLLADA 似乎是最好的選擇。COLLADA 是一個公開的三維數據 XML 交換格式。目前許多三維圖像軟件(如 3D Studio Max、Maya、SoftImage 等等)都有滙入滙出 COLLADA 的功能 (原生支持或透過插件),可以省下自行編寫插件的時間。
要在程式中支持讀寫 COLLADA 格式,最簡單的方法是使用 COLLADA 的程式庫。流行的程式庫有兩個: Feeling Software 的 FCollada 和Sony Entertainment 的 Collada DOM。兩個皆為 C++ 開源項目,並且皆使用 Document Object Model (DOM) 的方式存取 COLLADA 資料。
FCollada 的優點在於 API 比較簡單、可同時讀寫不同版本的 COLLADA 格式。而且,現時流行的 ColladaMax 和 ColladaMaya 插件都是 Feeling Software 採用 FCollada 編寫的,兼容性可能比較好。可是,一個壞消息是,Feeling Software 已於本年3月停止 FCollada 的更新,現在由一個開源隊伍維持該項目。
Collada DOM 是 Sony Entertainment 的產物 (事實上 COLLADA 也是由 Sony 發起的標準)。Collada DOM 的一個特別之處是,DOM 的 API 是由 COLLADA 的 Schema 用程式生成的。這樣的好處是,COLLADA 格式的版本更新只需要運行程式就能得到新的 API。不過這是雙面刃,Collada DOM 的缺點之一就是不能同時讀寫不同版本的 COLLADA 檔案。
經過一番比較後,現時選擇了 Collada DOM。它的一些吸引之處包括:
- 可選擇 XML 解析器
- 直接支持 Windows、Linux、OSX 和 PS3
- 包含一個 Collada RT 的開源項目,內有一個基於 OpenGL 的 COLLADA 檔案檢視器
最後一點最吸引我。這個檢視器除了支持基本的 geometry ,還支持 Skin、Skeleton、Animation、Collada FX 等等。這是一個很有參考價值的例子,我可以跟據這個例子去使用 Collada DOM。相對地,FCollada 並沒有這樣全面的開源例子。
昨晚編譯了 Collada DOM ,也測試了 Collada RT 檢視器和看了一些文檔。但是,要轉換 Collada 格式去引擎內部格式的話,目前的引擎尚欠一個層階式的物件系統。因此,還是要先設計遊戲物件的系統。
P.S. 曾經想過,半年都沒寫到甚麼出來,而科技一日千里,一個人在家裡做這樣的事情有意義嗎?時間雖然是一個問題,但我公司的一個引擎也有七、八年的歷史。如果可以做一個健全的架構,是應該可以與時並進的。一個不能敏捷地修改及更新的項目,很快就會結束它的生命。作為一個學習和分享經驗的平台,這就更沒所謂了。
P.P.S. 我中秋節便會回港陪產,黃金周後才回上海。屆時心理和生活也許又會作出很大的改變。
- Comments: 0
- Trackbacks: 0
- Search
- Feeds
- Meta




