1. 程式人生 > >Steamworks and Unity – P2P多人遊戲

Steamworks and Unity – P2P多人遊戲

working 事情 異常 研究 there 是否 ont else lock

之前我們討論過“如何把Steamworks.Net和Unity整合起來”,這是一個很好的開始,現在我們研究深一點,談一談Steam中的多人遊戲。這不是教程,但是可以指導你在你的遊戲中如何使用Steamworks。我們將使用Steamworks .Net的庫, steam_api.dll。 註意,你的遊戲運行,需要有一個Steam的App Id。你可以在這裏申請一個( greenlit),或者由Valve公司直接通過的遊戲也有一個Id。這是一個指南,如果你只是想知道Steam是否是一個方便的平臺,讀下去……

P2P 多人遊戲
Steamworks最偉大的特性就是它的匹配機制和P2P網絡通信,你不用擔心服務器的設置,所有的事情都已經準備就緒。
你可能不熟悉用P2P的連接來建一個多人遊戲,現在流行的方法是為客戶端和服務器商搭建獨立的實體。這種情況下,客戶端是遊戲本身,服務端是一個包括了服務端邏輯,連接了所有的玩家,保護玩家數據正常不受欺騙的應用程序。客戶端、服務端這種模式可能對大型遊戲更好,對於一些小的,非競技類遊戲,考慮放棄服務器部分,兩個客戶端直接對話可能會更好一些。 真的很簡單吧? Steamworks盡可能的讓它簡單。你不需對鏈接擔心,你只需要一個SteamID(SteamId是用戶唯一的標識,它是封裝在CSteamID對象中的一個很大的數,你可以用得到跟你互動的用戶的CSteamID,例如過通大廳(lobby)得到)。當你有了SteamID之後,你需要執行下面這個方面:
[C#] 純文本查看 復制代碼 ?
1 // class SteamNetworking public static bool SendP2PPacket(CSteamID steamIDRemote, byte[] pubData, uint cubData, EP2PSend eP2PSendType, int nChannel = 0)

pubData是我們想要發送的數據,cubData是發送數據的字節大小,eP2PSendType是傳送的方式,nChannal默認值為空,現在還沒有用,不用討論。 這裏是如何發送“Hello!"字串的例子:
[C#] 純文本查看 復制代碼 ?
1 2 3 4 5 6 7 CSteamID receiver = ...; string hello = "Hello!"; // allocate new bytes array and copy string characters as bytes byte[] bytes = new byte[hello.Length * sizeof(char)]; System.Buffer.BlockCopy(hello.ToCharArray(), 0, bytes, 0, bytes.Length); SteamNetworking.SendP2PPacket(receiver, bytes, (uint) bytes.Length, EP2PSend.k_EP2PSendReliable);


這裏有四種送傳的方式:
  • k_EP2PSendUnreliable – 小包,可以丟失,不需要依次發送,但要快
  • k_EP2PSendUnreliableNoDelay – 跟上面一樣,但是不做鏈接檢查,因為這樣,它可能被丟失,但是這種方式是最快的傳送方式。
  • k_EP2PSendReliable – 可靠的信息,大包,依次收發。
  • k_EP2PSendReliableWithBuffering – 跟上面一樣,但是在發送前會緩沖數據,如果你發送大量的小包,它不會那麽及時。(可能會延遲200ms)


另一邊做些什麽呢?

如果一個人發送了數據,另一個會以某種方式收到數據。當然,他們都有保密的安全措施。你不會發送數據到你範圍之外的其他Steamworks的客戶端上。一個Client能接收你的數據之前,他已經和你接受了你的請求,建立起一個P2P會話。

P2P會話請求發生在你第一次向SteamWork客戶端發送數據時。當你還有發送任何數據時,這個過程會自動重復(通常是幾分鐘一次),你應該只接受你希望的連接,例如,你所在大廳(lobby)的其他玩家。

如何接受一個會話請求?非常簡單!你可以像下面這樣寫代碼:

[C#] 純文本查看 復制代碼 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 // create a callback field. Having a field will make sure that the callback // handle won‘t be eaten by garbage collector. private Callback<P2PSessionRequest_t> _p2PSessionRequestCallback; void Start() { // setup the callback method _p2PSessionRequestCallback = Callback<P2PSessionRequest_t>.Create(OnP2PSessionRequest); } void OnP2PSessionRequest(P2PSessionRequest_t request) { CSteamID clientId = request.m_steamIDRemote; if (ExpectingClient(clientId)) { SteamNetworking.AcceptP2PSessionWithUser(clientId); } else { Debug.LogWarning("Unexpected session request from " + clientId); } }



這樣一個P2P會話就會被接受,你就可以開始…… 讀消息

所有消息都存在Steamwork消息對隊列中。你準備取它時就可以讀它。一般在Update()函數中要處理這些,你的應用可以盡快的檢查到是否有新消息。

[C#] 純文本查看 復制代碼 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void Update() { uint size; // repeat while there‘s a P2P message available // will write its size to size variable while (SteamNetworking.IsP2PPacketAvailable(out size)) { // allocate buffer and needed variables var buffer = new byte[size]; uint bytesRead; CSteamID remoteId; // read the message into the buffer if (SteamNetworking.ReadP2PPacket(buffer, size, out bytesRead, out remoteId)) { // convert to string char[] chars = new char[bytesRead / sizeof(char)]; Buffer.BlockCopy(buffer, 0, chars, 0, length); string message = new string(chars, 0, chars.Length); Debug.Log("Received a message: " + message); } } }

就是這些!

總結

這個指南沒有覆蓋清理部分(這不是必須的,因為沒有用到的會話會被自動清理)和異常處理。你可以在官方文檔讀到它們 official Steamworks documentation,。記住你需要成為Steam的夥伴才可能獲得,如果你還不是,我希望你讀完本文之後,可以考慮成為其中一員。

原文鏈接:http://blog.theknightsofunity.com/steamworks-and-unity-p2p-multiplayer/

Steamworks and Unity – P2P多人遊戲