• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            loop_in_codes

            低調做技術__歡迎移步我的獨立博客 codemaro.com 微博 kevinlynx

            談談我們的游戲邏輯服務器實現(一)

            原文鏈接:http://codemacro.com/2012/04/23/game-server-info-1/

            我們的邏輯服務器(Game Server,以下簡稱GS)主要邏輯大概是從去年夏天開始寫的。因為很多基礎模塊,包括整體結構沿用了上個項目的代碼,所以算不上從頭開始做。轉眼又快一年,我覺得回頭總結下對于經驗的積累太有必要。

            整體架構

            GS的架構很大程度取決于游戲的功能需求,當然更受限于上個項目的基礎架構。基礎架構包括場景、對象的關系管理,消息廣播等。

            需求

            這一回,程序員其實已經不需要太過關心需求。因為我們決定大量使用腳本。到目前為止整個項目主要還是集中在技能開發上。而這個使用腳本的度,就是技能全部由策劃使用腳本制作,程序員不會去編寫某個具體技能,也不會提供某種配置方式去讓策劃通過配置來開發技能。這真是一個好消息,不管對于程序員而言,還是對于策劃而言。但后來,我覺得對于這一點還是帶來了很多問題。

            實現

            基于以上需求,程序員所做的就是開發框架,制定功能實現方案。腳本為了與整個游戲框架交互,我們制定了“觸發器“這個概念,大概就是一種事件系統。

            這個觸發器系統,簡單來說,就是提供一種“關心“、”通知“的交互方式,也就是一般意義上的事件機制。例如,腳本中告訴程序它關心某個對象的移動,那么當程序中該對象產生移動時,就通知腳本。腳本中可以關心很多東西,包括對象屬性,其關心的方式包括屬性值改變、變大、變小,各種變化形式;對象開始移動,移動停止;對象碰撞,這個會單獨談談;定時器等。

            除了觸發器系統外,還有個較大的系統是游戲對象的屬性系統。對象的屬性必然是游戲邏輯中策劃最關心最容易改動的模塊。既然我們程序的大方向是盡可能地不關心策劃需求,所以對象屬性在設計上就不可能去編寫某個具體屬性,更不會編寫這個屬性相關的邏輯功能。簡單來說,程序為每個對象維護一個key-value表,也就是屬性名、屬性值表。該表的內容由腳本填入,腳本享有存取權限。然后腳本中就可以圍繞某個屬性來編寫功能,而程序僅起存儲作用。

            第三,怪物AI模塊。AI模塊的設計在開發周期上靠后。同樣,程序不會去編寫某類AI的實現。程序提供了另一種簡單的事件系統,這個系統其實就是一個調用腳本的方案。當關于某個怪物發生了某個事件時,程序調用腳本,傳入事件類型和事件參數。這個事件分為兩類:程序類和腳本類。腳本類程序不需關心,僅提供事件觸發API。程序類事件非常有限:怪物創建、出生、刪除。

            除了以上三塊之外,還有很多零散的腳本交互。例如游戲對象屬性初始化,角色進入游戲,角色進入場景等。這些都無關痛癢。

            接下來談一些關鍵模塊的實現。

            定時器

            整個GS的很多邏輯模塊都基于這個定時器來實現。這個定時器接收邏輯模塊的注冊,在主循環中傳入系統時間,定時器模塊檢查哪些定時器實例超時,然后觸發調用之。這個主循環以每幀5ms的速率運行,也即幀率1000/5。

            這個定時器是基于操作系統的時間。隨著幀率的不同,它在觸發邏輯功能時,就必然不精確。游戲客戶端(包括單機游戲)在幀率這塊的實現上,一般邏輯功能的計算都會考慮到一個dt(也就是一幀的時間差),例如移動更新,一般都是x = last_x + speed * dt。但,我們這里并沒有這樣做。我們的幾乎所有邏輯功能,都沒有考慮這個時間差。

            例如,我們的移動模塊注冊了一個固定時間值的定時器,假設是200ms。理想情況下,定時器模塊每200ms回調移動模塊更新坐標。但現實情況肯定是大于200ms的更新頻率,悲劇的是,移動模塊每次更新坐標都更新一個固定偏移。這顯然是不夠精確的。

            更悲劇的是,定時器的實現中,還可能出現跳過一些更新幀。例如,理論情況下,定時器會在系統時間點t1/t2/t3/t4分別回調某個邏輯模塊。某一幀里,定時器大概在t1回調了某邏輯模塊,而當該幀耗時嚴重時,下一幀定時器模塊在計算時,其時間值為t,而t大于t4,此時定時器模塊跳過t2/t3。相當于該邏輯模塊少了2次更新。這對于移動模塊而言,相當于某個對象本來在1秒的時間里該走5格,但實際情況卻走了1格。

            當然,當游戲幀率無法保證時,邏輯模塊運行不理想也是情有可原的。但,不理想并不包含BUG。而我覺得,這里面是可能出現BUG的。如何改善這塊,目前為止我也沒什么方案。

            移動

            有很多更上層的模塊依賴移動。我們的移動采用了一種分別模擬的實現。客戶端將復雜的移動路徑拆分為一條一條的線段,然后每個線段請求服務器移動。然后服務器上使用定時器來模擬在該線段上的移動。因為服務器上的阻擋是二維格子,這樣服務器的模擬也很簡單。當然,這個模塊在具體實現上復雜很多,這里不細談。

            碰撞檢測

            我們的技能要求有碰撞檢測,這主要包括對象與對象之間的碰撞。在最早的實現中,當腳本關心某個對象的碰撞情況時,程序就為該對象注冊定時器,然后周期觸發檢測與周圍對象的距離關系,這個周期低于100ms。這個實現很簡單,維護起來也就很簡單。但它是有問題的。因為它基于了一個不精確的定時器,和一個不精確的移動模塊。

            首先,這個檢測是基于對象的當前坐標。前面分析過在幀率掉到移動更新幀都掉幀的情況下,服務器的對象坐標和理論情況差距會很大,而客戶端基本上是接近正確情況的,這個時候做的距離檢測,就不可能正確。另一方面,就算移動精確了,這個碰撞檢測還是會帶來BUG。例如現在檢測到了碰撞,觸發了腳本,腳本中注冊了關心離開的事件。但不幸的是,在這個定時器開始檢測前,這兩個對象已經經歷了碰撞、離開、再碰撞的過程,而定時器開始檢測的時候,因為它基于了當前的對象坐標,它依然看到的是兩個對象處于碰撞狀態。

            最開始,我們直覺這樣的實現是費時的,是不精確的。然后有了第二種實現。這個實現基于了移動的實現。因為對象的移動是基于直線的(服務器上)。我們就在對象開始移動時,根據移動方向、速度預測兩個對象會在未來的某個時間點發生碰撞。當然,對于頻繁的小距離移動而言,這個預測從直覺上來說也是費時的。然后實現代碼寫了出來,一看,挺復雜,維護難度不小。如果效果好這個維護成本也就算了,但是,它依然是不精確的。因為,它也依賴了這個定時器。

            例如,在某個對象開始移動時,我們預測到在200ms會與對象B發生碰撞。然后注冊了一個200ms的定時器。但定時器不會精確地在未來200ms觸發,隨著幀率的下降,400ms觸發都有可能。即便不考慮幀率下降的情況,它還是有問題。前面說過,我們游戲幀保證每幀至少5ms,本來這是一個限幀手段,目的當然是避免busy-loop。這導致定時器最多出現5ms的延遲。如果策劃使用這個碰撞檢測去做飛行道具的實現,例如一個快速飛出去的火球,當這個飛行速度很快的時候,這5ms相對于這個預測碰撞時間就不再是個小數目。真悲劇。

            技能

            雖然具體的技能不是程序寫的,但正如把幾乎所有具體邏輯交給策劃寫帶來的悲劇一樣:這事不是你干的,但你得負責它的性能。所以有必要談談技能的實現。

            技能的實現里,只有一個技能使用入口,程序只需要在客戶端發出使用技能的消息時,調用這個入口腳本函數。然后腳本中會通過注冊一些觸發器來驅動整個技能運作。程序員一直希望策劃能把技能用一個統一的、具體的框架統一起來,所謂的變動都是基于這個框架來變的。但策劃也一直堅持,他們心目中的技能是無法統一的。

            我們的技能確實很復雜。一個技能的整個過程中,服務器可能會和客戶端發生多次消息交互。在最初的實現中,服務器甚至會控制客戶端的技能特效、釋放動作等各種細節;甚至于服務器會在這個過程中依賴客戶端的若干次輸入。


            下一篇我將談談一些遇到的問題。

            posted on 2012-04-25 16:54 Kevin Lynx 閱讀(6341) 評論(0)  編輯 收藏 引用 所屬分類: game develop

            精品国产婷婷久久久| 久久久久亚洲精品日久生情| 国产精品亚洲美女久久久| 久久噜噜久久久精品66| A级毛片无码久久精品免费| 久久精品免费一区二区三区| 怡红院日本一道日本久久| 久久亚洲AV成人无码| 久久亚洲精品视频| 亚洲精品乱码久久久久久蜜桃图片| 国内精品久久久久久麻豆| 亚洲精品无码久久千人斩| 久久天天躁狠狠躁夜夜2020| 国产成人无码久久久精品一| 欧美日韩精品久久免费| 久久精品二区| 99久久精品免费观看国产| 久久发布国产伦子伦精品 | 久久被窝电影亚洲爽爽爽| 国产免费久久精品99re丫y| 国产精品免费久久久久电影网| 亚洲精品国产美女久久久| 性做久久久久久久久老女人| 国产午夜福利精品久久| 韩国三级大全久久网站| 久久成人国产精品| 久久国产精品成人片免费| 久久久老熟女一区二区三区| 国产亚洲精品久久久久秋霞| 久久综合久久美利坚合众国| 一本色道久久综合狠狠躁篇 | 亚洲?V乱码久久精品蜜桃| 国产午夜电影久久| 国产国产成人久久精品| 99热热久久这里只有精品68| 成人亚洲欧美久久久久| 久久精品国产亚洲Aⅴ香蕉| 亚洲午夜精品久久久久久人妖| 国内精品久久九九国产精品| 久久综合九色综合久99| 国产69精品久久久久9999|