在遊戲編程精粹四有三篇文章講到了實體以及實體管理的實現方案,其中一篇文章說到了實體管理系統的四大要素:定義實體怎樣溝通的實體消息,實現一實體類代碼和數據的實體代碼,維護已經註冊在案的實體類列表,和用來建立、管理、發送消息的實體管理器。python
關於實體消息的內容以前討論事件機制的時候作過一點說明,其實這也就是按接口調用和按消息驅動的區別,如今mangos的作法是徹底的接口調用,因此引擎內部就沒有任何的實體消息。實體代碼實現和實體管理器是咱們重點要討論的內容。程序員
另有一篇文章也提到了使用類繼續的方式實現遊戲對象的兩大問題,一是它要求系統中的全部對象都必須從一個起點衍 生而成,也就是說全部對象類在編譯的時候已經肯定,這多是一個不受歡迎的限制,若是開發者決定添加新的對象類,則必需要對基類有所瞭解,方能支持新類。 另外一個問題在於全部的對象類都必須實現一樣的一些底層函數。編程
對於第二個問題,能夠經過接口繼承的方式來避免基類的方法太多。在mangos的實現中就採用了相似的方法,從 Object虛基類派生的Unit和WorldObject仍然仍是不可實例化的類,這兩種對象定義了不一樣的屬性和方法,分來實現不一樣類型的對象。在遊戲 內部能夠根據對象的實際類型來Object指針向下轉型爲Unit或WorldObject,以調用須要的接口。方法雖然不夠OO,也還能解決問題。可是 第一個問題是始終沒法避免的。函數
因此咱們便有了通用實體這麼一個概念,其主要方法是將原來基類的接口進行分類,分到一個個不一樣的子類中,而後以 對象組合的方式來生成咱們所須要的實際遊戲對象類型。這個組合的過程能夠經過腳本定義的方式,這樣即可以在運行時生成爲同的對象類型,也就解決了上面提到 的第一個問題。spa
通用實體的實現方法在目前的遊戲引擎及開源代碼中也能夠看到影子。一個是BigWorld,從提供的資料來看, 其引擎只提供了一個entity遊戲對象,而後由遊戲內容實現者經過xml和python腳原本自由定義不一樣類型的entity類型,每種類型可有不一樣的 property和不一樣的方法。這樣原來由基類定義的接口徹底轉移到腳本定義,具備很是強的靈活性。指針
另外還有一個是CEL中的entity實現。按照CEL的描述,entity能夠是遊戲中的任意對象,包括玩家 可交互的對象,如鑰匙、武器等,也能夠包括不能直接交互的對象,如遊戲世界,甚至任務鏈中的一部分等。entity自己並無任何特性,具體的功能實現需 要靠附加property來完成。簡單來講,property才定義了entity能夠作什麼,至於該怎麼作,那又是依靠behavior來定義。因此, 最終在CEL中一個遊戲對象實際上是由entity組合了多個property及多個behavior而生成的。調試
可是CEL中的property與BigWorld中的property意義不大同樣,在CEL中可定義的 property實際上是引擎內部要先提供的,好比其示例中所舉的pcobject.mesh、pcmove.linear、 pctools.inventory等,而BigWorld中的property是徹底的自由定製。從這個角度來說,其實能夠把CEL中的 property看做是遊戲的邏輯系統,也就是咱們上面所描述的,接口分類後所定義的子類。xml
由引擎內部提供可選擇的property與BigWorld所採用的徹底自由定製property其實本質上是 相同的。在用BigWorld實現的遊戲中,也不可能爲每種遊戲對象類型都徹底從頭定義property,基於代碼利用的原則,也會先定義一些小類,而後 在entity類型定義時以自定義property的方式來包含這些小類。固然,我沒有使用過BigWorld,上面的描述也只是基於遊戲實現的大原則所 作出來的。對象
描述的依然有些抽象,咱們能夠用wow及mangos代碼來講明一下。mangos中爲object定義了一個 屬性集合,根據對象類型的不一樣,這個屬性集的大小及保存數據也會有差別,另外遊戲對象內部含有處理不一樣遊戲邏輯的系統,如RestSystem、 FloodFilterSystem、VariousSystem等等,在player.h中以接口組的方式進行定義。繼承
若是要將這種結構改成咱們描述的通用entity系統,可讓object只提供property註冊和刪除的 接口,這裏的property定義與CEL中的相同,放在mangos中也就是上面說的RestSystem、FloodFilterSystem、 VariousSystem這些。而後也經過xml文件的方式定義咱們所須要的遊戲對象類型,如player,creature,item等,不一樣的對象 類型能夠選擇加載不一樣的property,加載的原則是須要哪些功能就加載哪些property。
對象的定義按上面的方法完成後,對象的實現也須要作一些修改。之前客戶端的消息是直接交由player來處 理,AI也是直接調用creature的接口來完成一些功能,如今通用的entity內部已經沒有任何可用的方法,全部的實現都轉到了property 中,因此須要由各個property實現本身來註冊感興趣的事件及消息,entity實現一個消息的轉發,轉給對此感興趣的property來處理。其他 的實現就沒有什麼不一樣了。
固然,咱們再作一點擴展,讓property不光由引擎來提供,用腳本自己也能定義property,而且能夠 經過xml來註冊這些property,這樣便實現了與BigWorld同樣的徹底自由特性。這其實也就是將不少用C++實現的功能轉移到了python 中,這種作法可做爲參考,但不必定對全部人合適,至少在我看來,這樣的實現也基本只能由程序員來作,因此讓程序員選擇本身最擅長的語言可能會更易於開發和 調試。