U3D 網絡教程再體驗2

哈羅,上一回我們已經成功在本機上搭建了客戶端和服務器,我們來回憶一下主要做了什麼事情

  1. 理解端口的概念
  2. 做了一個狀態判斷讓客戶端/服務器知道應該做什麼
  3. 通過指定的端口和IP讓Client連接上Server
好的,那麼今天,讓我們做一些更加勁爆的事情,製作一個自己的Uni-QQ!!是不是十分高端!那好,開始今天的教程吧。

知識儲備

我們需要之前寫過的Server和Client腳本,具體請參見:→戳我

理解一個新的概念RPC

—————————————————————————————————————————

是不是十分眼熟?NONONO這可不是People‘s Republic of China PRC,這是一種通過網絡從遠程計算機程序上請求服務而不需要了解底層網絡技術的協議。

他的工作原理大概爲

1.調用客戶端句柄;執行傳送參數

2.調用本地系統內核發送網絡消息 3.消息傳送到遠程主機

4.服務器句柄得到消息並取得參數

5.執行遠程過程

6.執行的過程將結果返回服務器句柄

7.服務器句柄返回結果,調用遠程系統內核 8.消息傳回本地主機 9.客戶句柄由內核接收消息

10.客戶接收句柄返回的數據

我們可以理解爲,Client有一堆對參數,Server有一個函數,我們從Client發起請求將參數傳過去,在Server端調用函數用來運算這些參數,然後得出結果返回給CLient端口。

簡單來說,RPC在OSI網絡通信模型中,跨越了傳輸層和應用程序。使得網絡開發更加便捷。

學有餘力請繼續戳我

—————————————————————————————————————————

而在Unity中設置RPC方法的屬性有這樣的說明

1,在所有連接端調用一個RPC函數。

2,調用的函數必須有@RPC標識([RPC]用於C#)。NetworkView必須附加到GameObject上,RPC函數才能夠被調用。NetworkView用於其他地方或者是僅用於RPC函數是沒有關係的。如果僅用於RPC函數,stateSynchronization應該被關掉,並且Ovserved屬性設置爲none,在整個場景中RPC函數的名稱應該是唯一的,如果不同腳本的兩個RPC函數具有相同的名稱,僅有一個會被調用。RPC調用總是確保執行的順序與他們調用的順序相同。用NetworkView.group爲NetworkView設置的通信組,被用於RPC調用。爲了獲取RPC自身的信息,可以添加一個NetworkMessageInfo參數到函數聲明中,它將自動包含這個信息。這樣的做的時候你不需要改變調用RPC函數的方式,可以參考手冊中的RPC部分以便獲取更多關於RPC的信息。可用的RPC參數爲int,float,string,NetworkPlayer,NetworkViewID,Vector3和Quaternion。

概括成一句話,在你想用RPC傳輸的S/C端口,都應該有一個同樣的RPC函數,還要用【RPC】標註起來。

好吧這裏就算不能理解也沒有關係,我們在實際調用到的時候就能慢慢理解了

改寫代碼

上次我們已經實現了通信,那麼這一次我們要做神馬呢,沒錯就是傳輸文本信息。那麼和上面的RPC有什麼關係呢。我們可以這樣理解,文本信息發送出去的時候並不是以字符串模式發送的而是一堆數據010100101000...什麼的。一般的協議都是轉碼加密過去解密輸出,RPC則是大家都有相同的解碼程序,我丟出一個請求,讓主機替我解碼就OK了...(上面請直接忽視,非正確解讀,不要放在心上)

Server

打開Server腳本,給她添加RPC。
首先新建一個公有變量msg用來存儲文本信息,並且初始化爲空
string msn = “”;
然後我們需要在服務器開啓的時候給她一個顯示文本的框,在OnServer最後添加下列代碼
GUILayOut.Box(msn);
這就生成了一個裝載着msn的小矩形盒子。

接下來我們就要給服務器端配置上RPC函數,記住這個RPC函數在所有端都應該一致,如果在不同端存在着同名的不同RPC函數,將只調用一個。寫入下列代碼
[RPC]//一定要記得標註這個標記

void ReceiveMessage(string msg,NetWorkMessageInfo info)
{
    msn = "Sender"+info.sender +"Message"+msg +"Time"+info.timestep;
}
//將發送者信息,發送的字符串,發送時間 打包給 msn
然後運行一下。
如果沒有什麼意外的話(就加了這麼點代碼都有意外我直接跳樓算了= =)會看到如下界面
沒有錯,只是多了一個用於顯示信息的小框框。

Client

打開Client腳本。
同樣的我們需要新建一個字符串變量來儲存文本信息,並且初始化爲空
string msn = “”;
我們回憶一下以前的版本,上一次,我們的客戶端的功能僅僅是按下按鈕,連接到服務器,並沒有更多需求,現在,我們需要在客戶端輸入文本,所以在狀態判斷中我們需要做一下改動
void OnGUI()
{
  switch(NetWork.peerType)
{
  case NetworkPeerType(Diconnected):
  StartConnect();
  break;
  case NetworkPeerType(Connecting)
  break;
  case NetworkPeerType(Server)
  break;
  case NetworkPeerType(Client)
  OnClient;//我們新定義一個函數用於實現輸入功能
  break;
}
}


//然後實現這個新功能
void OnClient()
{
  msn = GUILayout.TextArea(msn);
  if(GUILayout.Button("Send")
  {
    networkView.RPC("ReceiveMessage",RPCMode.All, msn);
  }
}

//同樣的我們需要配置RPC函數,直接將Server端的函數複製過來
[RPC]
void ReceiveMessage(string msg, NetWorkInfo info)
{
  msn = "Sender"+ info.sender +"Message"+msg +"Time" +info.timestamp;
}
列了這麼一大堆代碼肯定看着就煩吧= =沒關係我們來細說明一下。
第一個函數,在狀態判斷中,給(目前是Client狀態)添加了一個功能(該功能用於輸入)

第二個函數,實現輸入功能,直接調用了Unity GUI的自帶輸入框TextArea,然後執行了一個判斷,按下send按鈕之後調用RPC函數。

第三個就是習以爲常的配置RPC函數了。
這麼一分析,最重要的就是第二個函數中的那個NetWorkVIew.RPC()函數,這個函數的功能時調用所有連接端的RPC函數
這個函數有三個參數分別爲  
需要調用的RPC函數名  
RPC模式(全部,僅客戶端,其他,全部緩存)
發送給RPC函數的的參數


這樣是不是就理解了呢,我們將它拖拽到Camera上,然後刪掉Server的腳本。保存並運行,連接後你會看到如下


現在輸入文本並按下發送
服務器端口就會準確的顯示發送端口,發送文本了


總結

好了,到目前爲止,我們已經完成如下任務

  1. 理解了RPC的消息傳輸運作原理
  2. 實現了單向發送文本的功能

確切來說,與其將他稱之爲一個Unity版本的QQ,更不如說他是一個遊戲中常見的小喇叭系統。

那麼爲了完成一個QQ,我們應該完成消息的雙向交流,這個作爲課下思考,我們下一次會詳細講解。

那麼明天見~

————————————————————————————

最後爲懶人用戶提供現成的代碼和示例程序

下載鏈接用力點我


發佈了40 篇原創文章 · 獲贊 6 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章