天天看點

高層遊戲引擎——基于OGRE所實作的高層遊戲引擎架構(3)

第一部分 遊戲引擎技術簡介第一部分所需所有圖檔 引擎概述   曾經有一段時期,遊戲開發者關心的隻是如何盡量多地開發出新的遊戲并把它們推銷給玩家。盡管那時的遊戲大多簡單粗糙,但每款遊戲的平均開發周期也要達到8到10個月以上,這一方面是由于技術的原因,另一方面則是因為幾乎每款遊戲都要從頭編寫代碼,造成了大量的重複勞動。漸漸地,一些有經驗的開發者摸索出了一條偷懶的方法,他們借用上一款類似題材的遊戲中的部分代碼作為新遊戲的基本架構,以節省開發時間和開發費用。于是就慢慢産生了遊戲引擎。人對于遊戲引擎的概念是逐漸深入了解的,這個過程類似于其他技術的進步過程——畢竟遊戲引擎也是一個程式。這個了解所立足的就是對“封裝性”的了解。實際上在引擎這個概念下面更多的是每個人對引擎各自不同的了解:遊戲引擎隻是一個說法,至今為止沒有一個公認的定義。   近幾年一部分初學者所了解的引擎是“對底層功能的簡單封裝”,這個底層功能包括平台API、渲染API、音頻API、流媒體API等,這樣的引擎往往是一種C語言時代的思路,其劃分是來自于各個不同部分之間的“功能”關系,而非“邏輯”關系。經典概念包括:渲染核心、記憶體管理、骨骼動畫、幀動畫、檔案操作、實體庫、網絡庫等等。這個在廣為傳誦的網文《遊戲引擎剖析》(參考4)裡面有最為明确的體系劃分:   1、“渲染和構造3D世界,3D環境的光照和紋理”。渲染永遠是引擎最具有技術含量的部分,就不說那動辄千百塊錢的圖形卡了,單是圖形渲染相關技術的進步速率,就已經足以讓人瞠目結舌了。“什麼是渲染器,為什麼它又這麼重要呢?好吧,如果沒有它,你将什麼也看不到。它讓遊戲場景可視化,讓玩家/觀衆可以看見場景,進而讓玩家能夠根據螢幕上所看到的東西作出适當的決斷。”渲染所需的主要底層功能就是來支援OpenGL和DirectX的最新技術。由于這些技術不斷更改,導緻渲染器的更新換代也相當明顯。好在OGRE本身就是一個很巧妙的渲染器,它為我們隐藏了很多渲染器的複雜性,讓我們可以用近乎自然語言的方式來進行圖形處理。   2、“記憶體使用,特效和API”。圖形研究到高層次就不得不考慮到晶片的一些特性:例如顯存和記憶體管理、Shader和其它重要的參數。這也是屬于引擎必須染指的内容。   3、“模型與動畫,細節級别LOD”。遊戲引擎應該支援常見的模型檔案格式并很好地渲染他們,如果遊戲引擎需要用到自己的資料格式,那麼它需要為幾個主要的模型檔案格式做導出插件,以滿足美工的需要。   4、“實體,運動,效果”。實體系統可以讓遊戲盡可能地逼真。“作為遊戲開發者來說,無論我們做什麼,我們需要能夠檢測牆壁,檢測地闆,在世界中處理和其他對象的碰撞。這些是現代遊戲引擎的必備。”先進的實體系統如ODE,可以在保證效率的前提下精确處理實體和運動學理論和公式,其中甚至包括流體力學。   5、“聲音系統,音頻APIs”。耳朵也是人的一個重要的感覺和資訊獲得器官,這一點應該很好了解。   6、“網絡和連線遊戲環境”。網絡遊戲必備。如今大多數真正有長久生命力的遊戲都至少有一些連線成分。“最純粹的單人遊戲容易玩一次,也許兩次,或者甚至三次如果它是非常好的遊戲,但一旦遊戲結束,就被束之高閣了。如果你想要有任何長久生命力,那麼多人連線遊戲就是形勢的核心所在。”   7、“腳本系統”。你可以把遊戲腳本認為是電影腳本,它們兩者實質上是相同的。   8、“人工智能和導航”。   當按照這個思路建立了自己的引擎後,我們的引擎隻是一個功能引擎,它沒有任何邏輯關系。包括場景、地圖、物件、規則等一系列遊戲邏輯所直接相關的東西,它都沒法直接提供。這個時候我們所具有的引擎大約是如同下圖所示:  圖1-1 基本的的底層引擎核心結構  一種可怕的平鋪性的結構,互相之間沒有關聯或很少關聯。也就是說,它基本什麼邏輯都沒有實作,每一個遊戲你可以重用這些底層功能,除此之外,你需要重新寫所有邏輯,即便兩個遊戲在基本邏輯上基本相同。國外的遊戲引擎已經可以讓你脫離代碼,隻用腳本和編輯器就可以做遊戲了(這種開發手段叫做MOD),這種簡單的平鋪結構,沒有縱深,根本無法架起這樣一棟充斥了邏輯的大樓! 高層引擎概述   我們拿2D地圖來做一個例子,在這樣的引擎思路下,地圖隻是諸多圖元的拼接、Blt(發音Blit,位圖位塊傳輸)和互相遮擋。這個思路确實反映出來了地圖的本質,但是對于遊戲邏輯來說,它太細了。因為遊戲邏輯是不需要管你地圖圖元如何拼接、Blt和遮擋的。下圖左就是針對這種設計思路的,而下圖右則是提供了高層引擎的設計思路。通過對比可以發現,右邊的設計思路更符合OO的封裝原則,而左邊的主要是比較古老的過程式填鴨。  圖1-2 左邊是直接在應用程式裡寫死底層功能,右邊是在應用程式和底層引擎之間建立一個抽象層,有這個抽象層劃分和承擔遊戲的基本邏輯。在OO大行其道的今天,你會用哪一種方法?  而在這裡我們了解的引擎除了功能元素之外,同時包括一些邏輯意義的部分,即部分開發者交流中所說的“遊戲層引擎”或“高層引擎”,為何會存在這部分引擎呢?答案是為了友善我們表達遊戲的上層邏輯。底層遊戲引擎所立足的都是平台API,是與API嚴格相關的。目的就是為了要讓外界看不見API,專心做外界的邏輯部分,但底層引擎隻完成了一個目的就是通過封裝API來完成一定功能,封裝好的API是否就表明一定适應上層邏輯的要求呢?這根本不可能,因為它不是為了這個目的而存在的,例如骨骼動畫和上層邏輯有什麼關系呢?是以人們又提出了高層引擎的概念。這就回答了剛剛的問題,骨骼動畫是應當包含在物件邏輯内部實作的,對外部應該是透明的。如果遊戲邏輯需要細化到“誰誰誰,按照骨骼動作‘Walk2’來行走”,那就太麻煩了,這種情況下,比較普遍的做法是我們由來實作一個物件,然後為其設定一種狀态叫做STATE_WALK2,在物件自己的邏輯裡面當發現物件是處于這種狀态的時候就開始引發“Walk2”動作,這樣,最後的遊戲邏輯隻用簡化到說“那個誰,向前方走一步”就可以了。實際的處理是,引擎層擷取到了這個消息以後,向物件“誰”發送一個TranslateState(“走”)的消息,而物件“誰”獲得這個消息後,根據目前狀态自動進行狀态機的切換。對于邏輯的開發者來說,這一切都是封裝好的,透明的,他們隻需要知道“當我說‘A向前走’,A就會向前走”就可以了,這樣的引擎就不再簡簡單單是功能平鋪的平房,而是具有一定邏輯保障的大廈了。STATE_WALK2到Walk2的對應關系在不同遊戲引擎裡面可以通過不同方式實作,最初也是最簡單的方法是寫死(Hard-Code),這種方法速度快,然而犧牲了程式的維護性,會給測試帶來很大麻煩。現在,大部分的遊戲引擎可以通過配置檔案甚至是編輯器來解決此問題,以及與此類似的問題,這種資料驅動的方式使編碼邏輯更加簡單,同時也使設計者和導演工作更加友善。   下圖是我們使用一款外國引擎的編輯器時的場面,在這個編輯器裡面,既有物件編輯器,也有場景編輯器,同時也包括腳本——這個編輯器裡用它來實作我們所說的規則——的編輯器:  圖1-4 看着很像3DMax的一款遊戲編輯器,中國目前大部分遊戲工作室還沒有自己的實力開發這種高度內建的編輯器  把話題引回來,對比前面我們得出的結論,做一個遊戲,實際上就是在做場景(地圖+物件)、規則系統、GUI系統和I/O控制系統。那麼我們該怎麼做呢?建構一個過于集中的,把所有功能都實作了的高層系統,隻會降低高層引擎的可适應性,是以屬于高層引擎更多的是對它們提供支援,這些支援包括:基本資料結構群組織方式(例如物件連結清單及查詢操作、特殊的檔案資料)、工具集等。通過這一層的存在,最高層邏輯隻需要寫:在場景中放置幾隻飛鳥,按照Sin函數路線飛行。至于飛鳥飛行中是怎麼振翅,怎麼偏航,這是在物件系統的具體物件類——這裡是飛鳥——裡可以決定的。為了最終産品的邏輯需要,我們迫不及待的需要一個“高層遊戲引擎”,這是源自于一個很重要的思想,同時也是軟體工程的基礎思想:“軟體産生于需求”。底層引擎層次的劃分完全來自于平台和API的限制,因為畢竟我們要做的遊戲必須跟某一個平台相關。而高層次的引擎結構則是跟需要達到的目的嚴格相關的,因為這是它的存在動機。   實際上現在大部分引擎都是或多或少地包括了高層引擎部分的,然而高層引擎的劃分卻并不容易,大部分引擎所面向的還是FPS這種遊戲類型,做一款普遍适應的引擎是難上加難,因為不同遊戲所需要的高層不一樣。   我們這篇文章的基本目的,就是試驗當擁有一個現有的底層引擎的時候,如何建構一個高層引擎,以及如何讓這個高層引擎具有更強的适應性。 現在我們具有的引擎構造大抵如下:  圖1-4 按照現在的劃分誕生的高層引擎層的基本架構

繼續閱讀