用unity3d實現簡單的主伺服器連線
用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) 伺服器偵測到客戶端從伺服器斷開