1. 程式人生 > >用unity3d實現簡單的主伺服器連線

用unity3d實現簡單的主伺服器連線

unity3d實現簡單的主伺服器連線

參考自鷹大的網路例項

-------------------------------------------------華麗的分割線-------------------------------------------

一. UI以及主邏輯

//值得注意的是

//1Network.useNat已經不再使用 直接用一個變數替代它

//2GUILayout.BeginScrollView()有更好的過載函式來使用

//3Network.InitializeServer(players, port);也已經過時

//4.測試部分有些函式也已經過時,可以參考聖典做修改

//5.似乎有連不上主伺服器的問題

主邏輯函式

1.Awake()

l 初始化伺服器ipport

l 初始化視窗

l 初始化遊戲模式[可選]

2.OnGUI()

l 檢測是否有連線到伺服器或成為伺服器【開始時至少是正在連線了】

n 有的話載入場景

n 若沒有 有兩種可能:出錯了,尚未開始連線[分類處理]

u 若出錯 彈出視窗提示錯誤

u 此時一定是還沒連線 可以做快速遊戲或者玩家自定義加入兩種

l 若玩家點選了快速遊戲 【還沒有開始遊戲】

n 呼叫快速遊戲函式

l 若玩家點選了自定義遊戲

n 可以建立多種方式讓玩家登入[此時設計3種:)]

u 根據房間列表加入

u 根據伺服器ip[可以替換成建立伺服器的玩家名稱等等]

u 自己建立一個遊戲

n 玩家可以選擇退回到主選單

l 若玩家還沒有點選此時[應該設計選擇UI]

n 輸入玩家姓名

n 建立快速遊戲或自定義遊戲

實現函式

1) playNowFunction()快速遊戲

l 可以選擇在載入的時候退出遊戲

l 如果嘗試足夠多次連線主機都沒有成功 自己作為伺服器建立一個主機[建立房間]

l 呼叫具體處理快速遊戲的指令碼開啟遊戲

n 如果快速遊戲返回失敗 玩家自己建立一個主機[建立房間]

n 否則 此時系統正在嘗試快速遊戲,顯示處理進展[比如倒計時]

以下3個均為視窗回撥函式[建立一個適於互動的UI然後加入遊戲]

2) hostGUI()自己一個建立遊戲

l 建立視窗要求玩家輸入建立房間的必要資訊[

使用的埠 玩家數目]

l 確認資訊後建立房間

3) directConnectGUIWindow()通過ip加入遊戲

l 正在連線時 顯示訊息通知玩家正在連線

l 否則 此時尚未輸入資訊 `

n 玩家輸入目標房間資訊[ip port  是否useNat]

n 嘗試連線該目標房間

4) listGUI()房間列表

l 建立滾動條[讀取顯示主機列表中主機的資訊]

l 玩家可主動重新整理房間列表[可選]

l 若列表中沒有主機 顯式向玩家說明

二.多人遊戲具體實現

主邏輯函式[主要處理連接出現的問題]

1. Awake()

l 主機列表 new空間

l 連線測試

l 判斷並說明本機ip型別[公有or私有]

l 修改主伺服器資訊[可選]

2. Start() start中可做協同操作

l 請求主機列表

3. Update()

l 測試Nat

網路連線函式

1) OnFailedToConnectToMasterServer(info: NetworkConnectionError)  木有連線到主伺服器

l 本例中木有提供解決方法

2) OnFailedToConnect(info: NetworkConnectionError) 連線伺服器失敗

l 呼叫連線失敗處理函式

3) Connect(ip : String, port : int, usenat : boolean) 連線函式[感覺不是很必要]

似乎只在連線失敗處理重試時呼叫 【封裝價值不清楚】

l 根據引數連線伺服器

l 標識當前正在連線中

4) OnConnectedToServer() 客戶端成功連線到伺服器後呼叫

l 標識暫停網路功能的使用 因為在客戶端還在載入的時候,我們要防止從遊戲局內發出一些無法識別的網路資訊

l 儲存伺服器的ipport到偏好[便於以後的使用]

實現具體功能的呼叫函式

1.FailedConnRetry(info: NetworkConnectionError) 針對連線失敗的各種情況進行處理

l 當登入伺服器密碼輸入有誤 此時標識不再重試

l 當標識當前客戶端正在嘗試連線當前伺服器時[有根據主機呼叫過connect 系統會假定此時仍可以再次連線本伺服器]

l 若可以重試並且useNat==true並且當前嘗試的主機要求NAT穿透 我們此時就不用NAT穿透再連線一次當前伺服器  此處應該忘了對ip記錄儲存

l 否則當前的伺服器已經不能再連線了  將useNat重置、嘗試過的伺服器+1、標識當前沒有正在連線伺服器

l 當標識當前客戶端沒有正在嘗試連線當前伺服器時【即沒有使用快速遊戲開始遊戲】//沒理解透

l 由於本例沒有對非快速遊戲的連線做操作 先標識連線訊息為” Failed to connect!”

l 【似乎走不到這一步。。。】當伺服器要求useNat並且客戶端也使用了useNat連線時 不用useNat再嘗試一次【不能穿透也有可能連線的 比如沒有私有ip的聯網公有ip

l 否則連線一定失敗了 

根據連線失敗原因不同傳出不同的失敗提示、重置port、重置useNat為測試後的正式結果【當前客戶端的實際狀況】

2.TestConnection() 測試Nat 針對正在連線的輪詢測試連線 對結果進行反饋操作 1. 測試結果為ConnectionTesterStatus.Error

說明出現未知問題,可能是沒有可用的網路連線 標識完成Nat測試

2.  ConnectionTesterStatus.Undetermined:

說明尚未測試完成 標識未完成Nat測試

3.  ConnectionTesterStatus.PrivateIPNoNATPunchthrough 私有ip、不能做Nat穿透

此時要過濾使用了Nat穿透的客戶端 此時只能做局域網遊戲 標識過濾Nat主機,完成測試,useNat=true【此處不理解 不是應該不用穿透麼???但沒出現這個問題不知道具體情況如何 遇到的朋友幫忙看一下】

4.  ConnectionTesterStatus.PrivateIPHasNATPunchThrough 私有ip、能做Nat穿透

若是檢測正在探測公有ip,說明公有ip地址不能連線[被埠阻塞]

【若是伺服器,在開啟的情況下NAT穿透已經是啟用的了;若是客戶端,在主機請求時,開啟】

不論能否檢測到公有ip,都將useNat=true,標識完成NAT測試

5. ConnectionTesterStatus.PublicIPIsConnectable

可以直接連線公有ip地址,標記useNat=false、標識完成NAT測試

6. ConnectionTesterStatus.PublicIPNoServerStarted  公有ip被阻塞

a) 若是不是正在探測公有ip,說明可以繞過防火牆  強制測試NAT連線、標記正在探測公有ip、設計一段時間

b) 若一段時間後依舊阻塞,重置探測公有ip[false]useNat=false、標記完成NAT測試

7. 其他情況 出現錯誤

最後將當前的useNat標記為正式的Nat狀態

如果測試完成 將測試情況輸出便於檢查錯誤

對外的呼叫介面

l StartHost(players : int, port : int) 建立伺服器 對伺服器初始化封裝

l 若玩家填入小於修改至少為1[保證至少伺服器有一個玩家]

l 初始化伺服器

l PlayNow(timeStarted : float ) 快速遊戲 通過訪問遊戲列表嘗試連線所有的遊戲

l 遍歷主機列表 尋找沒有設定密碼、過濾穿透且主機沒有穿透或者使用穿透且沒有過濾的主機【不能穿透就不去穿透】【有一類是不能做穿透的】 找到作標記

l 若連線伺服器的玩家沒有超過限制

l 並且正在嘗試連線快速遊戲【感覺這裡有問題 連線太久就得讓人下線麼???】

l 若連線了太長時間  由定時器中斷

連線重試

l 如果當前沒有正在嘗試連線主機 且正在的嘗試主機小於當前輪詢的主機的編號

l 標記正在嘗試連線快速遊戲 正在嘗試的主機編號設為當前編號 標記最後連線的主機的useNat和本客戶端的useNat屬性與伺服器一致 連線該伺服器 標記最後連線快速連線的時間為當前時間

l 對主機列表做氣泡排序[目的是讓人員較少的房間增大被快速遊戲加入的概率 減少等待]

·FetchHostList(manual : boolean)  //請求主機限制[更新主機列表]   自動每隔2分請求一次 主動每隔5秒請求一次

三.遊戲載入完成後 處理連線、掉線、狀態

類的主邏輯

1.Awake()

允許網路資訊傳遞

若是伺服器,應該在主伺服器註冊遊戲

2.OnGUI() 輪詢處理當前的連線狀況

Network.peerType == NetworkPeerType.Disconnected 已斷開

Network.peerType == NetworkPeerType.Connecting 正在嘗試連線

Network.peerType == NetworkPeerType.Client 當前端是客戶端

Network.peerType == NetworkPeerType.Server 當前端是伺服器

可以選擇斷開

連線、斷開處理

客戶端:

1.OnDisconnectedFromServer(info : NetworkDisconnection) 從伺服器斷開

伺服器:

1.OnPlayerConnected(player: NetworkPlayer) 伺服器偵測到客戶端連線到伺服器

2.OnPlayerDisconnected(player: NetworkPlayer) 伺服器偵測到客戶端從伺服器斷開