遊戲的「連線與驗證」機制淺談
伺服端,客戶端,前端後端,這些稱呼到底是在說什麼?
網路遊戲,顧名思義就是需要網路連線的遊戲。
不過這次想講的當然沒有這麼簡單。
我們先以非單機,需要連線的「電腦遊戲」舉例,讓大家有個基本概念。
典型連線遊戲的基本雛型
所謂的連線遊戲,大都是由遊戲公司架設伺服器,然後由玩家電腦和伺服器連接,上傳或者下載資料,來達到遊戲內容或狀態的資料同步。
例如在遊戲中,玩家如果要「花費金幣」購買「回復藥水」,那麼處理的流程應該是這樣的:
為什麼會需要伺服器驗證呢?玩家方的金幣和藥水數量直接調整不是更快嗎?
其實這是為了防止玩家作弊,如果在客戶端(Client)直接進行計算的話,玩家可以利用第三方程式修改數據,例如增加金幣的數量,或是直接獲得藥水而不消耗金幣等等。這些玩家數據需要經過伺服器的檢驗,才能避免竄改。
名詞介紹
好,現在有了最簡單的認知,我們解釋一下名詞。
伺服端(Server side)
所謂的伺服端,或也稱服務端,是指相對於客戶端、專門處理客戶端發送的各種請求的單位。
例如常常在玩遊戲的時候,碰上連不到伺服器,或是遇到伺服器要關閉更新系統,這時就有可能是提供服務的伺服器沒有運轉,導致遊戲不能繼續進行。(也有可能是因為沒有網路所以連不上,或是客戶端的版本過舊等等)
客戶端(Client side)
所謂客戶端,就是相對於伺服端,是給到「用戶」手上的「軟體」。例如玩家下載下來的「遊戲安裝檔」或是「手機app」就是客戶端的程式軟體。
前端 V.S. 後端(Front end V.S. Back end)
有些人可能會把這兩個和Server或Client混淆了,其實前後端是更為彈性的稱呼。在網路連線中,Client就等於前端,Server可以稱為後端,但在系統界面層級,UI等使用者界面可以稱為前端,背後的運算邏輯層可以稱為後端。
因此前後端其實是一個相對的稱呼,不是絕對的職能分野。
(P.S.不過「前端工程師」在台灣的意義比較接近網頁或app工程師,是熟悉瀏覽器,網頁語言等等領域的職業。)
企劃雖然不用很了解實際編碼內容,但要知道連線運作原理,這樣在和程式溝通的時候才能更容易釐清問題,設計系統的時候也將這些考量進去會更好。
遊戲開發中,程式通常也會分為Server和Client兩端(程式人數少的話也會出現雙端/或稱為全端 的情況)。兩者所負責的領域是不同的。
Server端負責玩家資料的紀錄,處理和邏輯,Client則是負責和玩家看得到、接觸的到的一切內容有關。一般而言,一款遊戲的Server程式人員通常比Client少,因為Client的工作量會比較多。
延伸補充:除了前面介紹到的四個領域,還有像是資料庫、資訊安全等等不同的工程師領域。越大的專案,分工通常就需要越細。
以24人的遊戲開發團隊為例,通常「企劃:美術:程式:測試」的佔比大概是「1:2:2:1」(不同遊戲類型佔比可能差異很大)。
如果不考慮網頁跟營運等等的人員需求,24人中約有8人是程式,而這些程式中,通常是2~3人為Server端,5~6人為Client這樣的比例較為常見。
連線的種類?
有了基礎之後,我們來看一下連線的類型。
LAN( Local Area Network)區域網路
區域網路就是以一個區域內的多台電腦(或稱終端)連接在一起的網路。
例如小學的電腦教室,學生在學習時通常只開放區域網路,用來上交作業,但無法連線到外面(不能瀏覽Google之類的)。
或者是有些遊戲支持「區域連線」,就是利用區域網路讓兩台以上的電腦或主機進行連線。
區域網路可以藉由連接同一台路由器來實現。
WLAN(Wireless LAN)無線區域網路
簡而言之,就是Wi-Fi。基於無線技術架設的區域網路。
WAN(Wild Area Network)廣域網路/外部網路/公用網路
WAN就是利用連線協定,將跨大區域的電腦連接起來的技術。例如使用電腦上網瀏覽網頁或搜尋引擎等,就是使用這樣的技術。
以下三種只是生活中常見的種類,實際上還有非常多連線類型,有興趣可以參考維基的介紹。但原則上,只要能理解區域網路和廣域網路的差別就可以了。
來談談「資料驗證」吧!
遊戲中的資料驗證,通常是為了公平性,避免玩家任意竄改遊戲數據,扭曲原本設計師想要給予玩家的遊戲體驗,所以要驗收玩家方客戶端上傳的數據。
可以很簡單的想像成「所有在客戶端計算的結果,都有可能被造假」。
雖然並非所有玩家都會(甚至可以說很少玩家會)作弊,為了遊戲公平性,或是為了降低玩家的數據丢失風險,Server端的校驗是相當重要的。
其中,企劃常常扮演了判斷「哪些內容需要伺服器驗證」這樣設計工作。
常見需要「Server端」來處理的玩家操作包括「消耗付費資源」、「PVP向的系統」、「系統發放獎勵」等等。
越重要的數據,就越需要由Server來進行判斷。
例如「消耗付費寶石」這樣的操作,就一定要在Server端進行。
如果今天設計的是一個「抽轉蛋」的系統,而判斷玩家抽轉蛋結果的計算,放在客戶端,那會導致
- 玩家可以直接更改轉蛋結果再傳給Server
- 玩家抽到不想要的,直接關閉遊戲重裝,從Server重新回復數據再抽一次
- 玩家使用正常方式抽轉蛋,抽到想要的,但此時手機剛好沒電或遊戲閃退,資料沒有同步到Server,本地存檔又損毀,重開遊戲發現抽到的東西消失了
等等嚴重的結果。
只要牽涉到付費,公平性等等的機制,都要考慮是否經過Server來判斷。這是連線遊戲中相當重要的一環。
那麼為什麼不全部都給Server判斷就好呢?
很簡單,因為Server忙不過來(笑)。雖然全部都讓Server計算,的確就不會有造假的問題,但這樣會造成Server相當龐大的負擔。
舉個例子,以筆者有玩的日系手遊「公主連結Re-dive」為例,競技場就是採用客戶端計算的作法。讓發起進攻的玩家的手機自己計算戰鬥結果。
因此誰勝誰負,相當容易造假。只要客戶端改個角色的數據,常常一次普攻傷害破表,直接秒掉對面整隊。
對此,玩家可以自行觀看「戰鬥重播」來判斷對方有沒有使用外掛。如果發現重播結果和Server顯示的勝負結果不同,就可以向客服進行舉報。
有的讀者可能會問,這個競技場的計算,如果由Server端來計算結果,不就不會有外掛的問題了嗎?
這時,就要考量到伺服器的成本了。每一台伺服器,同一時間能處理的資料量是有限的。
假設這款遊戲有10萬名活躍玩家,而這些玩家平均每人每天會發起6次競技場戰鬥,則伺服器就要處理60萬筆戰鬥結果。
而且這些競技場的計算需求也不是平均分佈在一天24h,而是集中在中午午休,以及晚餐到午夜前的尖峰遊戲時段。
所以為了降低伺服器負擔,公主連結採取了由客戶端計算競技場結果傳送給伺服器,然後讓玩家舉報外掛這樣的方法。雖然體驗可能不夠好,但減少了很多潛在成本。
就像老師改考卷一樣
這邊打個比方。
可以想像成,伺服器就是老師,只有老師知道考卷的正確答案。
所有的玩家都是學生,他們需要交出考卷,由老師來批改答案。
但就在這其中,老師資源是有限的(伺服器效能),為了對應增加的學生,通常也需要多聘請幾個老師(多架設幾台伺服器)。
或是,降低老師的負擔,讓同學自己改其中一部份的題目(減少需要驗證的內容),例如選擇題部份讓學生自己改,老師只負責改簡答題。
但讓學生自己改的內容,就有可能出現「塗改答案」(向Server傳遞假訊息)、「假裝答對」(修改Client的結果)、「直接改分數」(調整Client數據)等等各種不同的作弊方法。
那麼,讓學生交換改就好啦?
交換考卷就可以避免作弊啦,也可以不需要老師了,只要知道正確答案就行!這不是學校常用的方法嗎?
其實,還真的有類似的想法喔。
這個把驗證工作交給其他學生(其他使用者)的作法,就是所謂的「去中心化」式驗證,也就是讓所有參與單位共同分擔驗證工作。
例如這幾年常常聽到的「區塊鍊」就是去中心化的代表之一。
額外閱讀:什麼是區塊鏈(Blockchain)?
(區塊鍊和遊戲驗證關聯較低,但因為剛好講到考卷這個比喻,這邊特別提一下,不想看的朋友可以直接跳過沒關係。)
這邊筆者不做太詳細的解釋,有興趣的朋友可以參考這篇:
額外閱讀:區塊鍊如何運作?(介紹比特幣的原理)
或是:維基百科上對區塊鍊的解釋
用上面提到的「考試卷」當作例子,可以簡單的理解為,區塊鍊就是「所有的考生」同時幫其他考生改考卷。最終,考卷的答案結果會被比對,如果有某一題某個考生的修改和其他人不同,就會以「多數的答案」作為正確的答案。
因此想要更改某一題的答案,就需要聯合至少一半數量的考生才能竄改結果。(當然也可以追加考生的數量,例如在區塊鍊中加入更多計算的電腦)
這種改考卷的方式,依靠的是「考生的基數」,只要考生越多,這個系統就越穩固,因為要作弊就需要聯合越多的考生,實行成功率就越低。
在區塊鍊技術中,如果一個駭客想要竄改交易紀錄,他就必須擁有一台佔地球所有運算區塊鍊的電腦中,佔比50%效能以上的超級電腦才行。(這在例如像是比特幣這種超級多人參與計算的電子貨幣來說幾乎是不可能的。)
這種不需要老師,就能夠穩定改考卷的作法,我們稱之為「去中心化」。
什麼是「弱聯網」?
接下來,我們要來談談遊戲設計中,連接伺服器傳輸資料的時機。
這裡我們要提一個詞,叫做「弱聯網」。是一個相較於強聯網(全程連網)遊戲的概念。這個詞最早是中國遊戲公司開始使用的,意思是不需要全程連網,只需要在重要的時機點請求伺服器驗證部份資訊即可。
以往的網路遊戲,需要持續連線才能提供遊玩服務(例如大型的線上MMORPG)。或者某些遊戲不用連到WAN,在區域範圍(LAN)內連網來實現客戶端之間的遊戲,也就是區域網路遊戲。
從MMO過度到Web Game(網頁遊戲)後,就有了「網頁表現和實際資料不同」這樣偽造表現的方法。(注1)
一直到移動型設備出現了之後,因為網路的不穩定性,全程需要連線的遊戲表現不好。像是玩家乘坐火車或捷運,在特定路段沒有網路訊號的時候,遊戲就容易因此中斷。
在這樣不穩定的網路連線品質下,遊戲研發廠商給了一個折衷方案,既不是完全不需要網路的單機遊戲,也不是需要全程連線的網路遊戲,也就是所謂的「弱聯網」方案。
基本原理就是,將部份邏輯運算工作交給客戶端,讓客戶端能獨立運作。只在特定的時間點(特殊時機,或是每隔一段時間)讓客戶端和伺服器進行一次資料同步。
舉個例子,像是龍族拼圖這款轉珠過關遊戲,玩家在「進入關卡」的那一個瞬間,需要和伺服器連線,確定玩家本身有足夠的體力,目標關卡有剩餘次數,而且玩家攜帶的隊伍合法(未使用作弊等竄改數據的方式)。這樣,伺服器才會下發一個「可以進入關卡」的封包訊息給遊戲客戶端,玩家也才能進入關卡當中開始遊戲。
但中途打小怪,打王,掉寶物這些內容,都是不需要連線就可以運作的,甚至玩家把遊戲隱藏到後台,等了兩天才又開起來,只要程式還在運作中,都可以繼續接著遊玩(當然,這取決於伺服器接不接受時間過長的通關請求)。
直到玩家「通關」的時候,才又與伺服器建立連線,告訴伺服端「我過關了」,並且將過關的數據傳送給伺服器。
也有些遊戲為了避免重複進出關卡來測試隨機獎勵,採用「一進關卡就扣除體力」以及「關卡進入時就決定了獎勵內容」這樣的作法,讓伺服器一開始就決定了發放的獎勵,來避免弱聯網不同步造成的種種異常。
總之,中途的遊玩過程不需要持續連線,這就是「弱聯網」的優勢。
P.S.通關結算時通常都會有一小段演出動畫,例如勝利動作或是Boss死亡動作,這也是客戶端在爭取和Server驗證的連線時間,降低玩家可能被網速問題卡住的小技巧。這美術資源的「預加載」有異曲同工之妙。
注1:在MMO時期,遊戲機制是設計成Server會主動發訊息給Client端。例如玩家A站在主城,玩家B過來攻擊,是由Server發消息給玩家A,告知他被攻擊了扣血。
但在進入了網頁遊戲後,由於網頁的特性是Client端如果不主動請求資料更新,那Server就不會發送狀態消息到Client端。(不可能讓Client端每秒都請求資訊,不適合HTTP的傳送機制)。
因此就衍生出讓Client端先作假表現,先演出,和實際資料不同步,再和Server驗證這樣的作法。也就是運算層和表現層分離,後續再請求驗證。
同步與異步
其實強弱聯網並不是近幾年才出現的新概念,在軟體的運作層面上,就是所謂的「同步」(Synchronous)和「異步」(Asynchronous)的差異。
異步(Asynchronous)也稱為非同步(Non-synchronous),兩個詞是一樣的意思,也都有人用。
所謂的「同步」,顧名思義,就是「兩邊一樣」的意思。在軟體工程中是個很重要的概念,是指軟體在處理事件時的方式。(在文章最後面會解釋這個「同步」和遊戲同步資料的差異)
「同步」就是事件的處理中,不能插入其他事件,需要等該事件處理完成後,才能進行下一個事件。
聽起來好像有點抽象對吧,沒關係,我們用白話一點的解釋。
「同步」就是當你領了號碼牌去櫃台時,櫃台處理你事務的期間,你不能做其他事情,要一直站在櫃台前面等。「非同步」則代表這段等待期間可以做其他事情。
(引用自:非同步和同步的差異)
上面這段文字,引用自一篇我認為解釋的很白話的文章,有興趣的可以點進去看一下。
在網路連線中,「同步」就是講求多個Client和Server之間的資料數據要盡可能保持一致,資料同步了以後,才執行下一個行為。
而非同步指的就是不需要等待資料傳輸到位,就可以執行其他行為。
我們拿剛剛的龍族拼圖做例子。
假設進入關卡之後,玩家每一次移動珠子,每一下攻擊,都需要和Server請求並且同步,才能執行下一個動作的話,會造成
- Server極大的計算負擔,別忘了同時有成千上萬的玩家正在進行遊戲。
- 玩家體驗很差,網路傳輸的速度影響了關卡的進行效率。如果每轉一次珠子就要等待一次連線,在火車或捷運上玩家玩起來會想摔手機的。
因此,所謂的「弱聯網」其實就是減少「同步連線」的佔比時間,只在特定的時機點同步資料(例如說關卡結束時),降低因為網路連線品質造成體驗不連續。
除了Client和Server之間的同步,如果是多人遊戲的話,多個Client之間的同步也相當重要。下面來聊一下幀同步和狀態同步的差異。
額外閱讀:[筆記] 認識同步與非同步 — Callback + Promise + Async/Await
工程向補充:「同步連線」因為連線的時間長且持續,通常使用的是Socket架構搭配Tcp或Udp。而非強連網遊戲因為處理的時機不定,通常用HTTP協議 (超文本傳輸協議 )來傳輸,HTTP(或HTTPS)協議有單次請求單次處理,處理完就斷開連線的特點,很適合用來做不需要全程連線的遊戲。
狀態同步和幀同步
幀同步這個詞,在前幾年騰訊王者榮耀大獲成功之後一度查詢率變得非常高。這邊簡單的解釋一下狀態同步和幀同步的差異。
狀態同步(State synchronization)
所謂的狀態同步,就是Client端會將資料傳給Server端做驗證,確定合法之後,Server才回應請求,或是讓其他Client端接到消息。
狀態同步最大的特色,就是Server端需要計算結果。即運算邏輯是放在Server端的。
例如說在MMORPG中,兩名玩家進行了PK,A玩家施放了一招技能,Server接到消息後,依照Client端上傳的狀態,確認A玩家的基本屬性,計算合法後,才將這個結果發給B玩家的Client端,告知B玩家受到多少傷害。
幀同步(Frame synchronization)
和狀態同步不同,幀同步的Server端不做邏輯校驗,只做訊息的傳遞中介者。即運算邏輯放在Client端。
雖然無法校驗請求是否合法,但幀同步有一些優點,包括
- 因為不用驗證,所以傳送的速度很快,Client端可以即時收到反饋。
- 容易實作「重播」的功能,因為Server只需要紀錄所有玩家在哪些時間點做了哪些操作,而不用紀錄龐大的玩家資料變化。(但同時,這個重播也不太好「倒退」,一旦開始播放了就只能播完,想找前面的時間點就只能從頭再放一次了)
- 和狀態同步相比,Server要做的事情少的多,開發的難度也較低。
- 斷線重連的機制實現容易。
- 網路傳輸量需求較少。相較於狀態同步每次都要傳輸大量的資料校驗,幀同步只需要傳送所有玩家的操作內容即可。
P.S.之所以叫做幀同步,就是因為每一幀處理一次傳輸內容,只將每幀的操作傳送到其他Client,所見即所得,因而得名。
兩者的使用時機
在需要反饋即時,並且沒有什麼資訊需要紀錄的遊戲類型上,幀同步的效果較好。例如說像格鬥遊戲(沒有積累要素,延遲容忍度低)或是MOBA類型的遊戲(需要重播,延遲容忍度低)會採用這種同步方式。
而其他的遊戲類型,例如MMORPG,卡牌等等,因為要考量的因素多,且對反應時間的需求較長,通常就採用狀態同步居多。在資訊安全或是防作弊的考量上,狀態同步的效果也比較好。
(參考資料:狀態同步和幀同步的差異(簡字))
至於兩者傳輸的資料量差異有多少呢?筆者這邊打個簡單的比方。
假設今天要直播兩名選手的象棋比賽,使用狀態同步,就是每當選手下完棋子之後,都把整張棋盤上每一個棋子的位置資料都傳給觀看者。
但實際上,有一個更簡單的傳輸方法,只傳輸哪一個棋子移動到哪個座標就可以了。也就是所謂的「棋譜」記法。
這樣一來,每次傳輸的時候就只需要傳送操作影響的內容本身就可以了,省下了其他沒有改變的內容量。
額外補充
實際上幀同步這個名詞並不完全正確,算是省略後的結果,就算是狀態同步,也可以使用幀(Frame)作為同步單位,因此實際上這裡的幀同步指的是「幀鎖定同步」。
詳情可以看一下下面這兩篇文章,會講的細一點:
延伸影片
在動作遊戲中,延遲式與回滾式機制的效果。以動畫方式展現,非常容易理解。
來談談「電磁紀錄」吧!
最後我們要來談的是,常常在遊戲開發中都被忽視的「紀錄」(Logfile)。
因為這個紀錄在遊戲過程中,不會影響玩家的遊戲體驗,甚至在測試時也不會被重視,因為他不屬於遊戲本身運作的「功能」。
但紀錄非常非常重要。怎麼說呢?
如果有個玩家致電客服,說他某個時間點獲得了某個裝備,但後來手殘賣掉了,要如何證明這個玩家說的是「實話」呢?就需要翻找伺服器關於獲取裝備和販售的紀錄了。
實際上,Server的運行如果沒有特別設計的話,是不會把玩家的所作所為記錄下來的,但這個動作卻非常重要。
埋Log紀錄點在遊戲中,就像是遊戲公司的眼睛。如果都沒有紀錄,那麼營運和研發人員對玩家的行為就像瞎了一樣什麼都看不到。
常見的紀錄包括「帳號登入登出」、「消耗或購買」、「玩家的文字溝通訊息」或「系統發放的獎勵」等等,Log紀錄越完善,就越能支持營運和研發人員。
除了常見的查找紀錄需求以外,Logfile最好也能反映出玩家在遊戲中的各種消費、活躍狀態。例如營運常見的術語ARPU(每用戶平均收入),DAU(日活躍用戶)等等數據,都需要有完善的紀錄系統來支持。
在寫企劃案的時候,不妨將這個也納入考量吧。
額外閱讀:此「同步」非彼「同步」!
其實,上面提到的「同步」和「異步」的概念,並不適合直接套用在遊戲中的強弱連網。
在軟體工程的定義中,同步和異步是事件發生時處理的方式,和連線一點關係都沒有!
嚴格來說,遊戲連線中的「同步」指的是資料同步,而軟體工程中的「同步」指的是事件的處理方式。但因為概念有些接近,而且也是使用同一個詞 Synchronous,因此常被混用。
所以,「異步」(Asynchronous)其實是只有軟體工程上才會有的。遊戲連線中的「弱聯網」,只是不需要常常和Server同步資料而已,跟軟體工程上的異步在本質上完全不同喔!
這次感覺都在聊一些瑣碎的技術知識,雖然很雜,但這些對於遊戲設計也是相當重要的部份喔!
了解這些原理,在和程式夥伴們溝通的時候,相信會更順利的。
那今天就先到這邊,我是水狼,我們下次見。
也可以到臉書追蹤我喔: 粉絲專頁連結
最後,請多利用我的個人文章列表,會持續更新: