標籤:
【c++端遊】
第一個接觸的遊戲項目,MMORPG,雖說MMORPG有蠻高的技術門檻,但那會大多在寫邏輯,很少深入底層,所以收穫有限。
win平台的,整體看分了三層:HomeServer、GameServer、四個DB進程(AccountDB、CharDB、LogDB、MailDB)。HomeServer負責登入排隊、同中控、平台互動等;GameServer是遊戲主體,內部除了資料庫、網路IO......遊戲邏輯相關的採用了單線程架構,有統一的Service迴圈架構,各種功能都是註冊進Service由主迴圈發起,比如:AI、Buff、移動、玩家資料寫庫...
線上玩家均放於記憶體池中,因單線程緣故,所以對強互動的支援很高(不必考慮並行作業一致性,rpc調用,rpc delay……)。類傳奇的戰鬥方式,也能應付密集計算。
可惜整體上的實現瞭解不多,深入研習過的只有三個部分:AI、網路模組、活動設計。
我們的AI是個基於虛函數的遞迴調用系統(本質用的解析器模式),附帶初始化時指定切換規則。簡單說來分為三個層級:
1)Do:執行基礎動作,如走路、攻擊、睡覺
2)Base:對Do層做簡單封裝,加入條件判斷、控制等,如隨機走、圍繞某點、跟隨
3)Logic:組合任意AI(Logic之間也能互相組合),有切換邏輯
同行為樹的區別:
1)邏輯判斷、行為寫在了一起
2)行為樹提取了通用節點,易於組織邏輯,比如
a)Selector Node
b)Sequence Node
c)Parallel Node
與外部系統互動上:
- 行為樹
- 弄個全域變數/dic,寫condition檢測
- 新增對應條件節點,Update時自己檢查
- 項目AI
- 通過事件類型,直接告訴AI切換行為( OnEvent )
- AI內部只關心自己的常規流程,比如巡邏、攻擊、跟隨…
- 特殊條件的邏輯,全交給外界事件處理……覺得這樣解耦挺不錯
- 發事件的地方,相當於決策層
- 行為樹裡的決策層,就是整個樹結構,行為都封裝在行為節點,或一棵小樹裡
- 相對而言行為樹的Condition Node就得拉入外部資料
這個AI系統,對比behaviac的行為樹,量級算是很輕了,核心代碼不超300行,容易把控細節,且實現大多玩法的AI不成問題。
網路模組,windows下固然是IOCP,這個可以另開貼子詳細描述,可挖的東西非常多。
活動設計,一位大神的作品,用c++做通訊核心、資料存放,具體邏輯全放Lua指令碼,擴充性非常高,且使用方便。舉個印象很深的例子:
用戶端需要的資料是非常雜亂的,很難統一格式,大神在指令碼層做了一套指令系統,svr端只需調同一介面發出指令即可,形如“Command#param1#param2#param3...”,用戶端指令碼中,只需註冊同名函數,即能自動調用。發送顯示資訊方便非常。
AI和IOCP有整理重構過,源碼地址:
https://github.com/3workman/InterpretAI
https://github.com/3workman/IOCP
【lua手遊】
這個項目的架構比較時髦,Logic、Gateway、Battle、Cross、SDK、Center、DB、World……齊全了。
多線程架構,c++做核心,Lua寫邏輯,其中Logic、Battle、Gateway、DB均可水平擴充。Cross負責後台模組之間的通訊,比如Battle同Logic(每個Battle、Logic完成初始化後,去Cross註冊下)。
先說優點:
1)使用方便,封裝的Rpc通訊,不必註冊訊息,且用的buffer傳參,代碼中連定義訊息結構體都省了;
2)起服流程設計很好,區分了Init、OnReady、Sequence等不同的介面調用階段,方便資料布局、熱更新;
3)藉助Lua強大的mettable,可以做到在業務層消滅所有資料庫操作,全底層控制,玩家資料自動同步用戶端;
4)支援邏輯事務性,server端大量操作,直接調介面,只要一個失敗,整個msg調用自動回退……爽的一比,不用預先搞一坨判斷;
缺點也明顯:
1)底層有大量的資料拷貝,效能不高,作為手遊伺服器,貌似僅支援5k線上
2)不支援強互動,同erlang、go內建的輕量線程不同,這裡的是系統級線程,玩家之間的資料修改加鎖的,且無法保證時序上資料的一致性,比如B先改了A的資料,C再去訪問,很可能C拿到的還是舊資料……批量玩家的資料互動,甚至需要開發人員自己預估競態,然後用對應技巧規避;
3)該伺服器原用於頁遊的,被設計成:一個伺服器處理序可跑多個服的資料,所以一個線程可能在跑幾個服的資料,而一個服的資料也會分在多個線程中。這個特性讓你在寫代碼時要額外注意,比如A、B兩玩家若分配在不同線程,那他們彼此是不可見的,用錯API就一直返回空了;再比如活動資料,要求全服一致,就不能隨便亂放了;
4)靜態生存期的資料種類太多了,有:玩家資料、玩家臨時資料、ShareData、玩家共用資料、lua檔案資料、全域_G資料……要理解它們各自存在的目的、適用情境~~可得一番功夫
雖說如此,但這個架構我覺得是很優秀的,尤其設計思想,幾個優點帶來的福音,寫代碼high爆了,開發效率非常高,一個熟手就能應付全部svr端任務。
【go手遊】
最近剛接觸,go是個很好用的語言,並發雖然沒erlang那麼牛逼,但一般的遊戲絕對夠用。且寫出的代碼可讀性高(也有不好的,沒奇技淫巧玩,硬式編碼寫法多了不少),靜態語言省了一大部分動態語言的debug時間。
說回架構,這個項目用的多進程架構:accountSvr、battleSvr、chatSvr、crossSvr、gamesvr、logSvr、mongoDB。
主邏輯伺服器gamesvr用的http短串連(上面兩個都是用的長串連,Battle戰鬥伺服器用的UDP),battleSvr、chatSvr用的tcp長串連同client互動。
每個模組都是單獨的一個進程,架構非常清晰,功能內聚,很有些每個模組提供一種服務的味道,可以繼續延伸,還在研習之中。
這個相比之前的伺服器,最大優點是簡單、清晰,學習掌握成本很低,且夠用……嗯,這也是go的設計哲學呐(*^__^*)
伺服器架構回顧