[譯]Unity – High Level Networking Concepts

原文:High Level Networking Concepts
※這篇都是字,有些可能會翻得有點鬼打牆( ´ー`)フゥー...

這個章節涵蓋了使用 Unity 的網路系統製作遊戲前,需要理解的概念。

What is Networking?

Networking 是在兩個以上的電腦間做做通訊。基本概念就是 Client 端(要求資訊的電腦)與 Server 端(回應要求的電腦)之間的關係。Server 端可以是一台專用的 host 機器,或者簡單地讓某個玩家(Client)同時作為其他玩家的 host。決定好 Server 端之後, client 會連結到它,兩台電腦就可以交換遊戲中需要的資料了。

創建一個 network 遊戲需要大量的注意力去定義細節。即使在 Unity 裡面使用/創建 network 是很簡單的,但 network 仍然是相當複雜。在 Unity 設計讓它盡可能可靠且具有彈性。This means that you, as the game creator, are responsible for things that might be handled in an automatic but less robust way in other engines.你做出的選擇對遊戲的設計上會有很大的影響,所以最好在製作初期就完成它們。理解 networking 概念會幫助你計畫你的遊戲設計做得更好,並且避免在執行時出狀況。

Networking Approaches

這裡有兩個方式來架構 network 遊戲稱為 "Authoritative Server" 和 "Non-Authoritative Server"。兩者都需要依賴 server 連結 client 並在它們之間傳送資料。同時也都提供隱私,在 end users 並不會直接的與其他人連結,或是將IP顯露給其他人。

Authoritative Server

這個 Authoritative Server 的方式需要 server 去負責所有世界的模擬、遊戲規則和處理其他 client 端的操作。每個 client 傳送它們的操作 (以 keystrokes 的形式或是請求行為)給 server 端,並且不斷地從 server 接收遊戲目前的狀態。Client 永遠不會自行讓遊戲狀態做出任何改變。作為替代,它會告訴 server 它想要做甚麼,然後 server 會處理要求,並回傳給 client 這項要求最後的結果。

基本上,玩家想要做甚麼和實際上發生了甚麼,這兩個中間是會格一層的。這會讓 server 在決定如何更新遊戲狀態之前,先去傾聽所有 client 的要求。

這個方法的優點就是讓 client 端的作弊更加困難。例如 client 不可能靠著告訴 server (and thereby other clients) 來作弊的殺掉敵人,因為他們沒有得到自己做決定的權利它們只可以告訴 server 有一把武器開火以及從哪來,然後讓 server 決定是否造成擊殺。

其他 authoritative server 的範例會讓多人遊戲依賴物理系統。如果讓每個 client 去執行自己的物理模擬,就會在所有 client 之間在同步上產生誤差。但是如果所有的物理物件是在中央 server 處理以及更新狀態,並發送回給所有的 client 端,來確保他們的狀態是一致的。

Authoritative servers 的一個潛在的缺點是訊息在 network 之間移動時會帶著一個 time。如果玩家按下了一個操作往前移動然後它花費了十分之一秒去和 server 交談,這個延遲就會被玩家查覺。一個解決的方案是使用所謂的 "client-side prediction(客戶端預測)"。這個技術的本質是讓 client 可以依照本機的版本更新,但它應該在需要的時候,可以接收來自 server 的更正。通常這應該只會被使用在單純的遊戲動作,而非會明顯遊戲狀態的邏輯改變。例如,不智地讓玩家回報某個敵人被擊殺的這種應該讓 server 決定的事情。

因為 client-side prediction 是一個進階的課題,我們並沒打算在這個指南裡面有太多著墨,但如果你想要知道,在書上或網路上有很多相關資訊。

比起 non-authoritative server,authoritative 會需要更大的處裡開銷。當 server 不需要去處理所有遊戲狀態的改變時,可以把大量的處理分散到 client 裡。

Non-Authoritative Server

Non-Authoritative server 不會去控制所有使用者的操作結果。玩家會各自處理操作和遊戲邏輯,接著傳送所有被決定好的動作給 server。Server 接著與世界狀態同步所有動作。從設計角度來看,這是很容易去實作的。當 server 只是所有 client 之間訊息傳遞的中繼點,而不用去額外處理 client 的操作。

在 client 處理所有物理和事件以及告訴 server 發生了什麼事情時,不需要任何類似"prediction(預測)"的方法。因為他們都是自己物件的"owners",也是整個 network 之中唯一能修改本機物件的代理人。

Methods of Network Communication

現在我們結束了基本的網路遊戲架構,現在開始探索更低階,關於 client 和 server 如何互相溝通。

這裡有兩個相關的方法:Remote Procedure CallsState Synchronization。在任何遊戲中不難看到這兩個方法。

Remote Procedure Calls

Remote Procedure Calls (RPCs)都是用來跨網路觸發其他電腦的功能,雖然當 server 和 client 兩者都在同一台電腦上執行時,"network"就只是代表一個訊息的管道。Client 可以發送 RPCs 到 server,然後 server 可以傳送 RPCs 到一個或多個 clients。這大多是用在該動作很少發生時。例如,當一個 client 翻動一個開關去打開門,這個就可以傳送一個 PRC 到 server,告訴它門被開啟了。Server 可以接著傳送其他 RPC 給所有 clients,觸發它們本機的功能去打開相同的門。它們用來管理和執行個別的事件。

State Synchronization

State Synchronization 用來共享不斷變化的資料。最好的範例就是玩家在動作遊戲中的位置。玩家總是會移動、跑動、跳躍等等。在網路內的其他玩家,即使該角色不是在本機控制的,但仍然需要去知道它在哪裡以及正在做甚麼事情。透過不斷發送玩家位置的資料,遊戲可以正確的顯示其他玩家的位置。

這類需要定期和頻繁在網路內傳送的資料。因為這個資料是 time-sensitive(對時間敏感的),然後它需要時間透過網入在機器間移動,近可能縮減傳送所需的資料就變得非常重要。簡單來說,狀態同步化通常都需要大量的頻寬,所以你需要盡可能減少頻寬的使用。

Connecting servers and clients together

連結 server 和 clients 可以是一個複雜的處理。機器可有私密和公開的 IP 位置,然後他們可以有本機或外在的防火牆阻擾存取。Unity networking 旨在盡可能處理各種狀況,但那並沒有一個萬用的方案。

私密位址是指IP無法直接從網路存取(它們也稱作"Network Address Translation or NAT" 位址,後面的方法會使用道它們)。簡單來說,私密位址會通過一個在 local router,它會將這個位址轉換成公開位址。經過這個動作,許多機器就可以使用私密位址透過一個單獨的公開 IP 位址和網路溝通。這是個很好的架構,直到在網路上的某地某人想要開始和一個私有位址連結之時。通訊通常是透過 router 的公開位址發生的,然後它應該要傳送資訊給私密位址。一個叫做"NAT punchthrough"的技術,使用了一個共享的 server 稱之為"facilitator(調停者)"來處理通訊,這樣私密位址也就可以從公開位址被搜尋到了。這個方式是先讓私密位址連結到 facilitator,然後透過 local router "punches(鑽)"出一個孔。這時 facilitator 就可以看到私密位址的公開 IP 以其它使用的 port,網路上的其他電腦這時也可以開始直接和這個無法被搜尋到的私密位址連結。(在實際操作中可以注意到更多 NAT punchthrough 的細節。)

公開位址就很直接了。在這裡主要的問題是連結會被內部或外部防火牆阻擋(內部防火牆是一個在本地執行用來防護的東西)。對於內部防火牆,使用者會被要求解除特定的 prot 讓遊戲 server 可以存取。相對之下,外部防火牆並不受使用者控制。Unity 會試圖去使用 NAT punchthrough 透過外部防火取得位址,但這個技術並不一定會成功。經測試,它通常都可以順利運作,但目前並沒有一個正式的研究報告上有這個部份的驗證。

剛才提及的連線問題對於 server 和 client 有不同的影響。Client 只需要請求離開 network 的管制,這是相對簡單的。如果 client 擁有一個公開位址就可以正常運作,因為只有在嚴格管制的企業網路才會被阻擋。如果 client 是私密位址,它可以連結至任何 server 除非該 server 是一個無法使用 NAT punchthrough 的私密位址(我們會在後面說明)。至於 server 端則較為複雜,因為 server 需要接收來自不明來源的連結。如果是公開位址,server 需要為遊戲開啟一個給網路存取的 port(也就是不被防火牆阻擋)。不然它就無法接收任何 client 的連結,也就無法使用了。如果 server 是私密位址,那它必須可以執行 NAT punchthrough 去允許連結並允許 NAT punchthrough 的穿透好讓 client 連結它。

Unity 提供工具去測試所有不同的連結狀況。當它被建立時就可以作連結。它會引發兩種狀況: 直接連結 ( client 需要知道 server 的 IP 位址或是 DNS 名稱)以及透過 Master Server 連結。Master Server 可以讓 client 知道 server 們的存在,這個必須是在不知道該 server 任何資訊時才會使用。

Minimizing Network Bandwidth

在複數 client 之間運作 State Synchronization,你不必同步每一個細節來顯示物件的同步。例如,當你同步一個角色時,你只需要在 client 之間發送它的位置和旋轉角度。即使該極為複雜,可能包含一個極深的 Transform 階層,但這整個階層的資料並不需要全部被共享。在你的遊戲內有大量的資料都是靜止無變化的,client 應該只需要在一開始放置好它,而非同步它。使用 infrequent 或 one-time RPC 呼叫就足以應付大部分功能的運作。善用安裝在遊戲中的資料,盡可能讓 client 自己處理。例如,如你所知的所有 texture 和 mesh 物件,它們通常是不會改變的,所以它們永遠不必執行同步。這是一個簡單的範例,但是它應該可以讓你思考哪些資料是絕對需要在 client 之間共享的。這才是你需要共享的資料。

哪個是需要被共享,而哪些是不需要的,這個工作可說是最困難的。特別是你沒有任何網路遊戲的製作經驗時。牢記,你可以把一個 PRC 發送到指定名稱的 level,讓所有 client 去讀取整個指定的 level 並加入它們自己的網路元件裡。盡可能架構讓 client 自給自足的運作系統進而減少頻寬的使用。

Multiplayer Game Performance

物理上的位置和 server 本身的效能會大大影響遊戲在它上面執行時的可玩性。位於遠離 server 大陸上的 client 可能就會感受到嚴重的延遲(lag)。這是網路在物理上的限制,唯一一個實際的解法就是盡可能讓 server 和使用它的 client 靠近,或是至少讓他們在同一個大陸上。

Extra Resources

我們蒐集了關於網路的資源連結:

Page last updated: 2011-11-18

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 變更 )

Twitter picture

You are commenting using your Twitter account. Log Out / 變更 )

Facebook照片

You are commenting using your Facebook account. Log Out / 變更 )

Google+ photo

You are commenting using your Google+ account. Log Out / 變更 )

連結到 %s