用unity3d實現簡單的主伺服器串連參考自鷹大的網路執行個體-------------------------------------------------華麗的分割線-------------------------------------------一. UI以及主邏輯
//值得注意的是
//1、Network.useNat已經不再使用 直接用一個變數替代它
//2、GUILayout.BeginScrollView()有更好的重載函數來使用
//3、Network.InitializeServer(players, port);也已經過時
//4.測試部分有些函數也已經過時,可以參考聖典做修改
//5.似乎有連不上主伺服器的問題
主邏輯函數
1.Awake()
l 初始化伺服器ip和port
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 儲存伺服器的ip和port到偏好[便於以後的使用]
實現具體功能的調用函數
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 修改至少為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) 伺服器偵測到用戶端從伺服器斷開