• <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

            低調(diào)做技術(shù)__歡迎移步我的獨(dú)立博客 codemaro.com 微博 kevinlynx

            談?wù)勎覀兊挠螒蜻壿嫹?wù)器實(shí)現(xiàn)(一)

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

            我們的邏輯服務(wù)器(Game Server,以下簡稱GS)主要邏輯大概是從去年夏天開始寫的。因?yàn)楹芏嗷A(chǔ)模塊,包括整體結(jié)構(gòu)沿用了上個(gè)項(xiàng)目的代碼,所以算不上從頭開始做。轉(zhuǎn)眼又快一年,我覺得回頭總結(jié)下對于經(jīng)驗(yàn)的積累太有必要。

            整體架構(gòu)

            GS的架構(gòu)很大程度取決于游戲的功能需求,當(dāng)然更受限于上個(gè)項(xiàng)目的基礎(chǔ)架構(gòu)。基礎(chǔ)架構(gòu)包括場景、對象的關(guān)系管理,消息廣播等。

            需求

            這一回,程序員其實(shí)已經(jīng)不需要太過關(guān)心需求。因?yàn)槲覀儧Q定大量使用腳本。到目前為止整個(gè)項(xiàng)目主要還是集中在技能開發(fā)上。而這個(gè)使用腳本的度,就是技能全部由策劃使用腳本制作,程序員不會(huì)去編寫某個(gè)具體技能,也不會(huì)提供某種配置方式去讓策劃通過配置來開發(fā)技能。這真是一個(gè)好消息,不管對于程序員而言,還是對于策劃而言。但后來,我覺得對于這一點(diǎn)還是帶來了很多問題。

            實(shí)現(xiàn)

            基于以上需求,程序員所做的就是開發(fā)框架,制定功能實(shí)現(xiàn)方案。腳本為了與整個(gè)游戲框架交互,我們制定了“觸發(fā)器“這個(gè)概念,大概就是一種事件系統(tǒng)。

            這個(gè)觸發(fā)器系統(tǒng),簡單來說,就是提供一種“關(guān)心“、”通知“的交互方式,也就是一般意義上的事件機(jī)制。例如,腳本中告訴程序它關(guān)心某個(gè)對象的移動(dòng),那么當(dāng)程序中該對象產(chǎn)生移動(dòng)時(shí),就通知腳本。腳本中可以關(guān)心很多東西,包括對象屬性,其關(guān)心的方式包括屬性值改變、變大、變小,各種變化形式;對象開始移動(dòng),移動(dòng)停止;對象碰撞,這個(gè)會(huì)單獨(dú)談?wù)劊欢〞r(shí)器等。

            除了觸發(fā)器系統(tǒng)外,還有個(gè)較大的系統(tǒng)是游戲?qū)ο蟮膶傩韵到y(tǒng)。對象的屬性必然是游戲邏輯中策劃最關(guān)心最容易改動(dòng)的模塊。既然我們程序的大方向是盡可能地不關(guān)心策劃需求,所以對象屬性在設(shè)計(jì)上就不可能去編寫某個(gè)具體屬性,更不會(huì)編寫這個(gè)屬性相關(guān)的邏輯功能。簡單來說,程序?yàn)槊總€(gè)對象維護(hù)一個(gè)key-value表,也就是屬性名、屬性值表。該表的內(nèi)容由腳本填入,腳本享有存取權(quán)限。然后腳本中就可以圍繞某個(gè)屬性來編寫功能,而程序僅起存儲(chǔ)作用。

            第三,怪物AI模塊。AI模塊的設(shè)計(jì)在開發(fā)周期上靠后。同樣,程序不會(huì)去編寫某類AI的實(shí)現(xiàn)。程序提供了另一種簡單的事件系統(tǒng),這個(gè)系統(tǒng)其實(shí)就是一個(gè)調(diào)用腳本的方案。當(dāng)關(guān)于某個(gè)怪物發(fā)生了某個(gè)事件時(shí),程序調(diào)用腳本,傳入事件類型和事件參數(shù)。這個(gè)事件分為兩類:程序類和腳本類。腳本類程序不需關(guān)心,僅提供事件觸發(fā)API。程序類事件非常有限:怪物創(chuàng)建、出生、刪除。

            除了以上三塊之外,還有很多零散的腳本交互。例如游戲?qū)ο髮傩猿跏蓟巧M(jìn)入游戲,角色進(jìn)入場景等。這些都無關(guān)痛癢。

            接下來談一些關(guān)鍵模塊的實(shí)現(xiàn)。

            定時(shí)器

            整個(gè)GS的很多邏輯模塊都基于這個(gè)定時(shí)器來實(shí)現(xiàn)。這個(gè)定時(shí)器接收邏輯模塊的注冊,在主循環(huán)中傳入系統(tǒng)時(shí)間,定時(shí)器模塊檢查哪些定時(shí)器實(shí)例超時(shí),然后觸發(fā)調(diào)用之。這個(gè)主循環(huán)以每幀5ms的速率運(yùn)行,也即幀率1000/5。

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

            例如,我們的移動(dòng)模塊注冊了一個(gè)固定時(shí)間值的定時(shí)器,假設(shè)是200ms。理想情況下,定時(shí)器模塊每200ms回調(diào)移動(dòng)模塊更新坐標(biāo)。但現(xiàn)實(shí)情況肯定是大于200ms的更新頻率,悲劇的是,移動(dòng)模塊每次更新坐標(biāo)都更新一個(gè)固定偏移。這顯然是不夠精確的。

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

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

            移動(dòng)

            有很多更上層的模塊依賴移動(dòng)。我們的移動(dòng)采用了一種分別模擬的實(shí)現(xiàn)。客戶端將復(fù)雜的移動(dòng)路徑拆分為一條一條的線段,然后每個(gè)線段請求服務(wù)器移動(dòng)。然后服務(wù)器上使用定時(shí)器來模擬在該線段上的移動(dòng)。因?yàn)榉?wù)器上的阻擋是二維格子,這樣服務(wù)器的模擬也很簡單。當(dāng)然,這個(gè)模塊在具體實(shí)現(xiàn)上復(fù)雜很多,這里不細(xì)談。

            碰撞檢測

            我們的技能要求有碰撞檢測,這主要包括對象與對象之間的碰撞。在最早的實(shí)現(xiàn)中,當(dāng)腳本關(guān)心某個(gè)對象的碰撞情況時(shí),程序就為該對象注冊定時(shí)器,然后周期觸發(fā)檢測與周圍對象的距離關(guān)系,這個(gè)周期低于100ms。這個(gè)實(shí)現(xiàn)很簡單,維護(hù)起來也就很簡單。但它是有問題的。因?yàn)樗诹艘粋€(gè)不精確的定時(shí)器,和一個(gè)不精確的移動(dòng)模塊。

            首先,這個(gè)檢測是基于對象的當(dāng)前坐標(biāo)。前面分析過在幀率掉到移動(dòng)更新幀都掉幀的情況下,服務(wù)器的對象坐標(biāo)和理論情況差距會(huì)很大,而客戶端基本上是接近正確情況的,這個(gè)時(shí)候做的距離檢測,就不可能正確。另一方面,就算移動(dòng)精確了,這個(gè)碰撞檢測還是會(huì)帶來BUG。例如現(xiàn)在檢測到了碰撞,觸發(fā)了腳本,腳本中注冊了關(guān)心離開的事件。但不幸的是,在這個(gè)定時(shí)器開始檢測前,這兩個(gè)對象已經(jīng)經(jīng)歷了碰撞、離開、再碰撞的過程,而定時(shí)器開始檢測的時(shí)候,因?yàn)樗诹水?dāng)前的對象坐標(biāo),它依然看到的是兩個(gè)對象處于碰撞狀態(tài)。

            最開始,我們直覺這樣的實(shí)現(xiàn)是費(fèi)時(shí)的,是不精確的。然后有了第二種實(shí)現(xiàn)。這個(gè)實(shí)現(xiàn)基于了移動(dòng)的實(shí)現(xiàn)。因?yàn)閷ο蟮囊苿?dòng)是基于直線的(服務(wù)器上)。我們就在對象開始移動(dòng)時(shí),根據(jù)移動(dòng)方向、速度預(yù)測兩個(gè)對象會(huì)在未來的某個(gè)時(shí)間點(diǎn)發(fā)生碰撞。當(dāng)然,對于頻繁的小距離移動(dòng)而言,這個(gè)預(yù)測從直覺上來說也是費(fèi)時(shí)的。然后實(shí)現(xiàn)代碼寫了出來,一看,挺復(fù)雜,維護(hù)難度不小。如果效果好這個(gè)維護(hù)成本也就算了,但是,它依然是不精確的。因?yàn)椋惨蕾嚵诉@個(gè)定時(shí)器。

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

            技能

            雖然具體的技能不是程序?qū)懙模绨褞缀跛芯唧w邏輯交給策劃寫帶來的悲劇一樣:這事不是你干的,但你得負(fù)責(zé)它的性能。所以有必要談?wù)劶寄艿膶?shí)現(xiàn)。

            技能的實(shí)現(xiàn)里,只有一個(gè)技能使用入口,程序只需要在客戶端發(fā)出使用技能的消息時(shí),調(diào)用這個(gè)入口腳本函數(shù)。然后腳本中會(huì)通過注冊一些觸發(fā)器來驅(qū)動(dòng)整個(gè)技能運(yùn)作。程序員一直希望策劃能把技能用一個(gè)統(tǒng)一的、具體的框架統(tǒng)一起來,所謂的變動(dòng)都是基于這個(gè)框架來變的。但策劃也一直堅(jiān)持,他們心目中的技能是無法統(tǒng)一的。

            我們的技能確實(shí)很復(fù)雜。一個(gè)技能的整個(gè)過程中,服務(wù)器可能會(huì)和客戶端發(fā)生多次消息交互。在最初的實(shí)現(xiàn)中,服務(wù)器甚至?xí)刂瓶蛻舳说募寄芴匦А⑨尫艅?dòng)作等各種細(xì)節(jié);甚至于服務(wù)器會(huì)在這個(gè)過程中依賴客戶端的若干次輸入。


            下一篇我將談?wù)勔恍┯龅降膯栴}。

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

            综合久久久久久中文字幕亚洲国产国产综合一区首 | 久久这里只有精品首页| 国产A三级久久精品| 99久久er这里只有精品18| 国产亚洲美女精品久久久| 亚洲欧美日韩中文久久| 亚洲欧美日韩精品久久| 无码国内精品久久人妻蜜桃| 久久996热精品xxxx| 精品久久久久久久久午夜福利| 狠狠人妻久久久久久综合| 人妻无码αv中文字幕久久| 国产一区二区精品久久凹凸| 日产精品久久久久久久| 亚洲精品99久久久久中文字幕 | 久久精品国产99久久久古代 | 一本久久免费视频| 国产精品伊人久久伊人电影| 久久久久高潮毛片免费全部播放 | 久久91精品国产91久久小草| 久久精品国产精品亚洲精品| 三级片免费观看久久| 精品国产热久久久福利| 国产精品久久精品| 久久精品国产亚洲av高清漫画| 久久婷婷五月综合色99啪ak| 99久久精品免费看国产一区二区三区 | 欧美精品国产综合久久| 精品久久久久中文字| 91久久精品电影| 精品99久久aaa一级毛片| 国产精品美女久久久网AV| 国产成人久久精品二区三区| 91精品国产高清久久久久久91| 久久综合久久综合久久| 久久综合九色综合精品| 国产精品免费久久| 久久精品国产欧美日韩99热| 久久国产色av免费看| 精品久久人妻av中文字幕| 久久精品一区二区三区不卡|