使用 XNA 建立遊戲/網路/網路和點對點
好吧,我會做到的。 - project79
一個非常重要的點是:從一開始就決定是否支援遊戲的網路功能。由於頻寬、延遲、丟包以及所有這些因素的組合,你不能只通過網路傳送你的輸入。會有你必須在玩家面前隱藏的錯誤。為什麼、哪些錯誤以及如何隱藏將在後面提到。首先,我們來了解一下游戲和網路的一些理論。

大多數人聽到點對點(簡稱 P2P)時會想到非法的東西。但它並不非法。它只是一種組織網路的方式。
在這裡,每臺機器(稱為節點)都知道其他所有節點,或者至少知道它想要與其通訊的所有其他節點。因此,一個節點可以直接與另一個節點通訊,這比客戶端/伺服器方法更快。此外,你也不需要一臺具有大量頻寬需求的機器。但要量力而行。頻寬最差的節點決定了所有其他節點的速度(對於與它的連線)。(每個人都與每個人連線。因此,B 的下載速度與 A 的上傳速度相同)
如果每個節點都是平等的,沒有人比其他人擁有更多,包括邏輯。因此每個人都在計算自己世界的一部分,因此作弊很容易 - 沒有人(可以)控制你。另一個缺點是尋找其他節點的方式。玩家不能輸入 10 個 IP 地址,你不能掃描整個網路。
進一步閱讀維基百科

這是網路中最典型的網路架構。在這裡,每臺機器(客戶端)都連線到中間的一臺機器(伺服器)。通常,資訊的流動是客戶端將他們的輸入傳送到伺服器,伺服器計算結果並將其傳送回客戶端。因此,邏輯集中在一箇中央點,玩家無法操縱它。因此,作弊很難。還有建立遊戲會話的優勢,因為客戶端只需要一臺機器的地址。
但也有缺點。由於每個人都透過伺服器通訊,因此該機器上的頻寬負載要高得多。該機器也應該更強大。另一個問題是延遲。每個訊息都必須透過伺服器傳遞,這會導致更長的距離和更長的交付時間。
進一步閱讀維基百科
就像混合動力車一樣,這裡既有客戶端/伺服器也有 P2P。下面提到了兩種有趣的型別。
第一個解決了尋找其他節點的問題。某種程度上,你需要一個像伺服器一樣的中央點。那麼為什麼不使用一個呢?一個玩家啟動多人遊戲會話,並在後臺啟動一個小伺服器。其他人只需要加入一個會話。也許他們輸入第一個玩家的 IP 地址,或者在區域網中,遊戲會查詢伺服器。找到伺服器並設定一個準備就緒的標記後,所有客戶端的 IP 地址以及一些初始化資訊(地圖、此會話的規則)將被共享。現在每個客戶端都可以與其他每個客戶端通訊。因此伺服器停止,網路變為 P2P,遊戲開始。
第二個解決了作弊問題。由於每個節點都擁有整個邏輯(並使用它),因此沒有權威機器可以說 A 的結論是錯誤的。但如果有一個大型權威機器控制著邏輯,那將是客戶端/伺服器,這對於頻寬原因來說可能是不可行的。所以將邏輯(對於重要的部分)拆分成小的獨立部分,並將它們分佈到節點上。因此,A 控制團隊旗幟,而 B 控制其他東西,等等。
通常有 12 到 250 千位元組每秒可用。但建議只使用 8 千位元組每秒。這是 99% 使用者擁有的頻寬(《光環 3》測試版期間的資料收集(2007 年)[1](上行中值 44,下行中值 42))
那麼為什麼只有這麼一點呢?
服務提供商總是想銷售他們的產品。即使在最佳狀態下,你也無法獲得合同中規定的全部功率。頻寬受線上人數、你到路由器的距離、其他人的活動等等的影響。也許你的隊友沒有良好的連線。但他的上傳是你的下載,反之亦然。這也是上行速度與下行速度相似的理由。
好的。物理。
我們都知道光速是 299,792,458 米每秒(真空)。我們也知道資料包是透過光或電傳送的。但這些線纜中是否有真空?沒有,它是光纖或銅線,將我們的資料包速度降低到 194,865,097 m/s(65%)。因此,以下是一些從柏林到其他地點的距離以及每個資料包所花費的時間(理論時間和往返時間;網站主機只在城市附近)
| 城市 | 距離(公里) | 計算時間(毫秒) | 測量時間(毫秒)(32 位元組 ping) |
|---|---|---|---|
| 倫敦 | 910 | 4.67 | 137(www.proteusinvestigations.co.uk) |
| 比勒陀利亞 | 8,660 | 44.41 | 272(mybroadband.co.za) |
| 墨西哥城 | 9,710 | 49.79 | 671(mexicocity.gob.mx) |
| 悉尼 | 15,960 | 81.85 | 432(cityofsydney.nsw.gov.au) |
那麼為什麼測量時間總是高出那麼多呢?因為你沒有直接的(物理)連線到這些計算機。資料包必須被路由,每個路由器都需要一些時間才能將你的資料包放到正確的線路(5-50 毫秒)。你的調變解調器也會增加 10 毫秒。
因此,遊戲中延遲的一個好數字是 270 毫秒。
這個問題(也稱為“高延遲”)歸結為您為資料包使用哪種協議的問題。對於遊戲,UDP 是主要使用的協議,但它並不總是可靠的。UDP 協議將資料包傳送到網路並忘記它們。因此,如果資料包丟失,就無法再找到它。在即時測試中,2% 的資料包丟失是平均延遲,但對於遊戲,要做好高達 10% 資料包丟失的準備。每個資料包都可能出現損壞,以及資料流順序混亂和錯誤。另一種協議,TCP,解決了大多數這些問題,但速度太慢,無法產生太大影響。TCP 在多人遊戲中最好的應用是回合制遊戲或延遲不是大問題的其他環境。
無論您在編寫什麼程式,都應該考慮一個要點:使用正確的(更小的)資料型別。一個位元組只是一個 int 的四分之一。矩陣可以用一個四元數和一個向量表示,這樣只需要 7 個值而不是 16 個值。由於字串有開銷,應避免使用。您還可以將多個布林值放在一個位域中(好吧,這實際上並沒有更小),但您可以將多個(不是 32 位長的)數字放在一個 32 位整數中(透過位移)。
另一種方法是不每次都發送整個世界(或您的角色的特定狀態),只發送變化。
不要過於精確!考慮影像,您不會發送每個畫素的真實值。除了對畫素進行分組之外,值還會被量化。因此,與其傳送弧度(或度數)中的精確角度,不如將其轉換為度數並將值四捨五入為自然數。或者,如果 256 個不同的值足夠,則將其轉換為一個位元組。
其他更多 XNA/C# 特定的可能性是:[2]
- 如果一個浮點值不能大於 1,則將其轉換為一個 Alpa8(減少 75%)。
- 如果一個浮點值可以大於 1,則將其轉換為一個 Halfsingle(減少 50%)。
- Vector2 ⇒ HalfVector2
- Vector4 ⇒ HalfVector4
- 如果一個 Vector3 被歸一化 ⇒ Normalized101010
- 如果不是 ⇒ 3 個 Halfsingle
- Quaternion ⇒ NormalizedByte4
- Color.packedValue
舉個簡單的例子。您有一個小型遊戲,有 8 個玩家,以 30 幀/秒的速度執行。每個玩家都有一個位置,一個他所看的方向,以及一個布林值作為某種狀態。每幀您都會將您的資料傳送給所有其他玩家。
但是,我們不是透過網際網路傳送的嗎?所以我們至少還需要三樣東西。IP 頭部是 20 位元組,UDP 是 8 位元組。那是傳輸,但不知何故,另一臺計算機必須知道如何處理資料包。所以我們的框架的頭部仍然缺失。Live 需要 16 個位元組,XNA 需要大約 7 個位元組。因此,我們有 51 個額外的位元組沒有儲存任何資料。
好的。15.6 kB 是我們 8 kB 限制的兩倍。如果您想透過 XNA 傳送語音,則需要為每個隊友每秒新增 500 個位元組。
在這個例子中,我們有 25 個位元組的(對於遊戲)有用資料和 51 個位元組的開銷,這意味著我們使用了 67% 的頻寬來填充“浪費”。我們不能完全減少這種浪費,但可以相對減少。如果我們將傳送次數減少到每三幀一次(每秒 10 次,典型的頻率是每秒 10 到 20 次)。假設我們仍然會發送當前幀的資料。因此,我們只會傳送 5.2 kB 的資料,但我們仍然有 67% 的開銷,並且有用資料更少。所以我們將最後兩幀與我們的“傳送”幀結合起來。為了簡化操作,我們只在每一幀中傳送我們的完整位置和方向 - 更好的做法是在第一幀中傳送位置,而在第二幀和第三幀中使用更小的資料型別(方向也是如此)。
75 個位元組的有用資料與 51 個位元組的開銷,這意味著只有 40% 的浪費,資料完全相同。聽起來很棒,我們仍然將整個世界未壓縮地傳送給所有人。只是一個往返時間的比較。首先,我用 5250 位元組的資料包大小對我的網站進行 ping 測試,然後使用 15960 位元組的資料包大小。檢視結果
| 最小值 | 最大值 | 平均值 | |
|---|---|---|---|
| 5250 位元組 | 110 | 255 | 140 |
| 15960 位元組 | 217 | 317 | 264 |
我認為我無需解釋,更多的資料也意味著更多延遲。
考慮以下問題
- 在遊戲中我必須和誰交談?
- 我必須知道我身後是什麼嗎?
- 灰塵顆粒向哪個方向反彈?
- 哪些星星在哪裡?
- Linus 需要知道我穿的靴子還是我看著哪裡嗎?
- ...
好的。對於某些事情,您可能已經失去了思考,而對於其他事情,可能只是一個“什麼……”。您可以忘記最後一種問題,如果您還記得,不是每個客戶端都必須擁有相同的世界,而是彼此足夠相似。其他問題應該被優先考慮。
在很多情況下,這並不容易。但其背後的想法是。玩遊戲時,您已經擁有隊友的一些資料。即使它們來自過去,您也可以將它們結合起來計算他們的移動方式。這就是預測,平滑現在處理的是所犯的錯誤。因為當有新的資料包時,顯示原始位置而不是預測並不那麼好(化身會跳躍)。這就是它如此困難的原因。
但是,您可以透過將物體的物理狀態與其其餘狀態分離,並將它(以及物理模擬所需的所有內容)放在巢狀的輔助結構中來使其稍微容易一些。還可以為模擬傳送更多資料。更多(和正確)的資料會導致更好的預測。因此,資料必須更少地傳送。
由於敵人的位置只是一個預測或它的平滑和“現實”,玩家不能真正依賴於他看到的敵人就在那裡 - 記住,我們生活在平行世界中,有些事情被認為是不同的,而另一些事情只是猜測。因此,當您將書扔到特定位置時,其他人可能在他的世界中稍微偏左一點,因此您錯過了他。因此,最好是扔向這個人,讓您的計算機計算您是否擊中了他 - 以及您是如何錯過的。
您還必須隱藏伺服器(或其他對等體)響應玩家行為的往返時間。這很簡單,用動畫隱藏它。讓角色說點什麼,或者讓他四處看看,好像在尋找路徑。您也可以使用它與其他玩家同步。
- ↑ 一些部分可以在幻燈片 18 和 20 中找到 聯網、交通擁堵和薛定諤的貓
- ↑ Chad Carter - Microsoft XNA Game Studio 3.0 Unleashed - 第 561 頁