第一部分 游戲引擎技術(shù)簡(jiǎn)介第一部分所需所有圖片 引擎概述
曾經(jīng)有一段時(shí)期,游戲開發(fā)者關(guān)心的只是如何盡量多地開發(fā)出新的游戲并把它們推銷給玩家,。盡管那時(shí)的游戲大多簡(jiǎn)單粗糙,,但每款游戲的平均開發(fā)周期也要達(dá)
到8到10個(gè)月以上,這一方面是由于技術(shù)的原因,,另一方面則是因?yàn)閹缀趺靠钣螒蚨家獜念^編寫代碼,,造成了大量的重復(fù)勞動(dòng)。漸漸地,,一些有經(jīng)驗(yàn)的開發(fā)者摸索
出了一條偷懶的方法,,他們借用上一款類似題材的游戲中的部分代碼作為新游戲的基本框架,以節(jié)省開發(fā)時(shí)間和開發(fā)費(fèi)用,。于是就慢慢產(chǎn)生了游戲引擎,。人對(duì)于游戲
引擎的概念是逐步深入理解的,這個(gè)過程類似于其他技術(shù)的進(jìn)步過程——畢竟游戲引擎也是一個(gè)程序,。這個(gè)理解所立足的就是對(duì)“封裝性”的理解,。實(shí)際上在引擎這
個(gè)概念下面更多的是每個(gè)人對(duì)引擎各自不同的理解:游戲引擎只是一個(gè)說法,,至今為止沒有一個(gè)公認(rèn)的定義。
近幾年一部分初學(xué)者所理解的引擎是“對(duì)底層功能的簡(jiǎn)單封裝”,,這個(gè)底層功能包括平臺(tái)API,、渲染API、音頻API,、流媒體API等,,這樣的引擎往往
是一種C語言時(shí)代的思路,其劃分是來自于各個(gè)不同部分之間的“功能”關(guān)系,,而非“邏輯”關(guān)系,。經(jīng)典概念包括:渲染核心、內(nèi)存管理,、骨骼動(dòng)畫,、幀動(dòng)畫、文件
操作,、物理庫(kù),、網(wǎng)絡(luò)庫(kù)等等。這個(gè)在廣為傳誦的網(wǎng)文《游戲引擎剖析》(參考4)里面有最為明確的體系劃分:
1,、“渲染和構(gòu)造3D世界,,3D環(huán)境的光照和紋理”。渲染永遠(yuǎn)是引擎最具有技術(shù)含量的部分,,就不說那動(dòng)輒千百塊錢的圖形卡了,,單是圖形渲染相關(guān)技術(shù)的
進(jìn)步速率,,就已經(jīng)足以讓人瞠目結(jié)舌了,。“什么是渲染器,為什么它又這么重要呢,?好吧,,如果沒有它,你將什么也看不到,。它讓游戲場(chǎng)景可視化,,讓玩家/觀眾可
以看見場(chǎng)景,從而讓玩家能夠根據(jù)屏幕上所看到的東西作出適當(dāng)?shù)臎Q斷,。”渲染所需的主要底層功能就是來支持OpenGL和DirectX的最新技術(shù),。由于這
些技術(shù)不斷更改,導(dǎo)致渲染器的更新?lián)Q代也相當(dāng)明顯,。好在OGRE本身就是一個(gè)很巧妙的渲染器,,它為我們隱藏了很多渲染器的復(fù)雜性,讓我們可以用近乎自然語
言的方式來進(jìn)行圖形處理,。
2,、“內(nèi)存使用,,特效和API”。圖形研究到高層次就不得不考慮到芯片的一些特性:例如顯存和內(nèi)存管理,、Shader和其它重要的參數(shù),。這也是屬于引
擎必須染指的內(nèi)容。
3,、“模型與動(dòng)畫,,細(xì)節(jié)級(jí)別LOD”。游戲引擎應(yīng)該支持常見的模型文件格式并很好地渲染他們,,如果游戲引擎需要用到自己的數(shù)據(jù)格式,,那么它需要為幾個(gè)
主要的模型文件格式做導(dǎo)出插件,以滿足美工的需要,。
4,、“物理,運(yùn)動(dòng),,效果”,。物理系統(tǒng)可以讓游戲盡可能地逼真。“作為游戲開發(fā)者來說,,無論我們做什么,,我們需要能夠檢測(cè)墻壁,檢測(cè)地板,,在世界中處理
和其他對(duì)象的碰撞,。這些是現(xiàn)代游戲引擎的必備。”先進(jìn)的物理系統(tǒng)如ODE,,可以在保證效率的前提下精確處理物理和運(yùn)動(dòng)學(xué)理論和公式,,其中甚至包括流體力
學(xué)。 5,、“聲音系統(tǒng),,音頻APIs”。耳朵也是人的一個(gè)重要的感覺和信息獲得器官,,這一點(diǎn)應(yīng)該很好理解,。
6、“網(wǎng)絡(luò)和連線游戲環(huán)境”,。網(wǎng)絡(luò)游戲必備,。如今大多數(shù)真正有長(zhǎng)久生命力的游戲都至少有一些連線成分。“最純粹的單人游戲容易玩一次,,也許兩次,,或者
甚至三次如果它是非常好的游戲,但一旦游戲結(jié)束,就被束之高閣了,。如果你想要有任何長(zhǎng)久生命力,,那么多人連線游戲就是形勢(shì)的核心所在。”
7,、“腳本系統(tǒng)”,。你可以把游戲腳本認(rèn)為是電影腳本,它們兩者實(shí)質(zhì)上是相同的,。 8,、“人工智能和導(dǎo)航”。
當(dāng)按照這個(gè)思路建立了自己的引擎后,,我們的引擎只是一個(gè)功能引擎,,它沒有任何邏輯關(guān)系。包括場(chǎng)景,、地圖,、物件、規(guī)則等一系列游戲邏輯所直接相關(guān)的東
西,,它都沒法直接提供,。這個(gè)時(shí)候我們所具有的引擎大約是如同下圖所示: 圖1-1
基本的的底層引擎核心結(jié)構(gòu) 一種可怕的平鋪性的結(jié)構(gòu),互相之間沒有關(guān)聯(lián)或很少關(guān)聯(lián),。也就是說,,它基本什么邏輯都沒有實(shí)現(xiàn),每一個(gè)游戲你可以重用這些底層
功能,,除此之外,,你需要重新寫所有邏輯,即便兩個(gè)游戲在基本邏輯上基本相同,。國(guó)外的游戲引擎已經(jīng)可以讓你脫離代碼,,只用腳本和編輯器就可以做游戲了(這種
開發(fā)手段叫做MOD),這種簡(jiǎn)單的平鋪結(jié)構(gòu),,沒有縱深,,根本無法架起這樣一棟充斥了邏輯的大樓! 高層引擎概述
我們拿2D地圖來做一個(gè)例子,,在這樣的引擎思路下,地圖只是諸多圖元的拼接,、Blt(發(fā)音Blit,,位圖位塊傳輸)和互相遮擋。這個(gè)思路確實(shí)反映出來
了地圖的本質(zhì),,但是對(duì)于游戲邏輯來說,,它太細(xì)了。因?yàn)橛螒蜻壿嬍遣恍枰苣愕貓D圖元如何拼接、Blt和遮擋的,。下圖左就是針對(duì)這種設(shè)計(jì)思路的,,而下圖右則
是提供了高層引擎的設(shè)計(jì)思路。通過對(duì)比可以發(fā)現(xiàn),,右邊的設(shè)計(jì)思路更符合OO的封裝原則,,而左邊的主要是比較古老的過程式填鴨?!?圖1-2
左邊是直接在應(yīng)用程序里硬編碼底層功能,,右邊是在應(yīng)用程序和底層引擎之間建立一個(gè)抽象層,有這個(gè)抽象層劃分和承擔(dān)游戲的基本邏輯,。在OO大行其道的今天,,
你會(huì)用哪一種方法? 而在這里我們理解的引擎除了功能元素之外,,同時(shí)包括一些邏輯意義的部分,,即部分開發(fā)者交流中所說的“游戲?qū)右?#8221;或“高層引擎”,
為何會(huì)存在這部分引擎呢,?答案是為了方便我們表達(dá)游戲的上層邏輯,。底層游戲引擎所立足的都是平臺(tái)API,是與API嚴(yán)格相關(guān)的,。目的就是為了要讓外界看不
見API,,專心做外界的邏輯部分,但底層引擎只完成了一個(gè)目的就是通過封裝API來完成一定功能,,封裝好的API是否就表明一定適應(yīng)上層邏輯的要求呢,?這
根本不可能,因?yàn)樗皇菫榱诉@個(gè)目的而存在的,,例如骨骼動(dòng)畫和上層邏輯有什么關(guān)系呢,?因此人們又提出了高層引擎的概念。這就回答了剛剛的問題,,骨骼動(dòng)畫是
應(yīng)當(dāng)包含在物件邏輯內(nèi)部實(shí)現(xiàn)的,,對(duì)外部應(yīng)該是透明的。如果游戲邏輯需要細(xì)化到“誰誰誰,,按照骨骼動(dòng)作‘Walk2’來行走”,,那就太麻煩了,這種情況下,,
比較普遍的做法是我們由來實(shí)現(xiàn)一個(gè)物件,,然后為其設(shè)置一種狀態(tài)叫做STATE_WALK2,在物件自己的邏輯里面當(dāng)發(fā)現(xiàn)物件是處于這種狀態(tài)的時(shí)候就開始引
發(fā)“Walk2”動(dòng)作,,這樣,,最后的游戲邏輯只用簡(jiǎn)化到說“那個(gè)誰,,向前方走一步”就可以了。實(shí)際的處理是,,引擎層獲取到了這個(gè)消息以后,,向物件“誰”發(fā)
送一個(gè)TranslateState(“走”)的消息,而物件“誰”獲得這個(gè)消息后,,根據(jù)當(dāng)前狀態(tài)自動(dòng)進(jìn)行狀態(tài)機(jī)的切換,。對(duì)于邏輯的開發(fā)者來說,這一切都
是封裝好的,,透明的,,他們只需要知道“當(dāng)我說‘A向前走’,A就會(huì)向前走”就可以了,,這樣的引擎就不再簡(jiǎn)簡(jiǎn)單單是功能平鋪的平房,,而是具有一定邏輯保障的
大廈了。STATE_WALK2到Walk2的對(duì)應(yīng)關(guān)系在不同游戲引擎里面可以通過不同方式實(shí)現(xiàn),,最初也是最簡(jiǎn)單的方法是硬編碼(Hard-Code),,
這種方法速度快,然而犧牲了程序的維護(hù)性,,會(huì)給測(cè)試帶來很大麻煩?,F(xiàn)在,大部分的游戲引擎可以通過配置文件甚至是編輯器來解決此問題,,以及與此類似的問
題,,這種數(shù)據(jù)驅(qū)動(dòng)的方式使編碼邏輯更加簡(jiǎn)單,同時(shí)也使設(shè)計(jì)者和導(dǎo)演工作更加方便,。
下圖是我們使用一款外國(guó)引擎的編輯器時(shí)的場(chǎng)面,,在這個(gè)編輯器里面,既有物件編輯器,,也有場(chǎng)景編輯器,,同時(shí)也包括腳本——這個(gè)編輯器里用它來實(shí)現(xiàn)我們所
說的規(guī)則——的編輯器: 圖1-4
看著很像3DMax的一款游戲編輯器,中國(guó)目前大部分游戲工作室還沒有自己的實(shí)力開發(fā)這種高度集成的編輯器 把話題引回來,,對(duì)比前面我們得出的結(jié)論,,做
一個(gè)游戲,實(shí)際上就是在做場(chǎng)景(地圖+物件),、規(guī)則系統(tǒng),、GUI系統(tǒng)和I/O控制系統(tǒng)。那么我們?cè)撛趺醋瞿???gòu)建一個(gè)過于集中的,,把所有功能都實(shí)現(xiàn)了的高
層系統(tǒng),只會(huì)降低高層引擎的可適應(yīng)性,,因此屬于高層引擎更多的是對(duì)它們提供支持,這些支持包括:基本數(shù)據(jù)結(jié)構(gòu)和組織方式(例如物件鏈表及查詢操作、特殊的
文件數(shù)據(jù)),、工具集等,。通過這一層的存在,最高層邏輯只需要寫:在場(chǎng)景中放置幾只飛鳥,,按照Sin函數(shù)路線飛行,。至于飛鳥飛行中是怎么振翅,怎么偏航,,這
是在物件系統(tǒng)的具體物件類——這里是飛鳥——里可以決定的,。為了最終產(chǎn)品的邏輯需要,我們迫不及待的需要一個(gè)“高層游戲引擎”,,這是源自于一個(gè)很重要的思
想,,同時(shí)也是軟件工程的基礎(chǔ)思想:“軟件產(chǎn)生于需求”。底層引擎層次的劃分完全來自于平臺(tái)和API的限制,,因?yàn)楫吘刮覀円龅挠螒虮仨毟骋粋€(gè)平臺(tái)相關(guān),。
而高層次的引擎結(jié)構(gòu)則是跟需要達(dá)到的目的嚴(yán)格相關(guān)的,因?yàn)檫@是它的存在動(dòng)機(jī),。
實(shí)際上現(xiàn)在大部分引擎都是或多或少地包括了高層引擎部分的,,然而高層引擎的劃分卻并不容易,大部分引擎所面向的還是FPS這種游戲類型,,做一款普遍適
應(yīng)的引擎是難上加難,,因?yàn)椴煌螒蛩枰母邔硬灰粯印?
我們這篇文章的基本目的,就是試驗(yàn)當(dāng)擁有一個(gè)現(xiàn)有的底層引擎的時(shí)候,,如何構(gòu)建一個(gè)高層引擎,,以及如何讓這個(gè)高層引擎具有更強(qiáng)的適應(yīng)性。
現(xiàn)在我們具有的引擎構(gòu)造大抵如下: 圖1-4 按照現(xiàn)在的劃分誕生的高層引擎層的基本框架