前言
上篇我們學習了Unity用戶端如何和Photon伺服器建立連接配接,這篇是如何與伺服器進行資料的互動。
慣例,基于上篇的伺服器項目MyGameServer,Unity用戶端項目進行進一步的學習。
用戶端與伺服器互動流程圖解
前面我們有談到,當用戶端請求連接配接Photon伺服器時,伺服器會為每個用戶端建立一個PeerBase對象用于處理各種請求以及相應,如圖

一個ClientPeer對應一個PeerBase,這個PhotonServer對這些用戶端Peer和伺服器端Peer進行管理。
這裡分伺服器端和用戶端進行學習。
用戶端
上節課我們定義了一個PhotonEngine.cs來進行和伺服器的互動,實作了Photon.Client.IPhotonPeerListener的接口。也就是ClientPeer。這裡有幾個重要的方法。
- OnStatusChanged——當連接配接狀态改變時調用,peer對象中有個成員屬性PeerState用于标志目前連接配接狀态,peer.PeerState連接配接狀态有以下幾種
- PeerStateValue.Connecting——正在連接配接伺服器中
- PeerStateValue.Connected——已連接配接伺服器
- PeerStateValue.Disconnecting——斷開伺服器中
- PeerStateValue.Disconnected——已斷開伺服器連接配接
- PeerStateValue.InitializingApplication——伺服器初始化中
- OnOperationResponse——伺服器成功響應後執行,方法參數OperationResponse operationResponse封裝了響應的資訊,這裡講解兩個比較重要的資訊
- operationResponse.OperationCode——響應碼,用于區分響應資訊,既然會有區分響應的響應碼,當然一定會有區分請求的請求碼,在講解伺服器端時會進一步展開
- operationResponse.Parameters——響應的參數,是一個Dictionary<byte, System.Object>,學過javaweb或者後端開發的童鞋,會比較熟悉這種類型的資料。這個資料便是伺服器傳回的遊戲資料串。
- 注意:隻有發送請求給伺服器後,伺服器端調用SendOperationResponse方法才會調用
- OnEvent——伺服器主動發送消息給用戶端時調用,方法參數EventData eventData和OperationResponse有異曲同工之妙
- 注意:無需發送請求給伺服器,當伺服器調用SendEvent方法時調用
- DebugReturn——當伺服器傳回一個Debug資訊時調用。
以上四個IPhotonPeerListener接口中的方法用于監聽用戶端與伺服器互動的各種操作,主要的遊戲資料同步都需要使用以上的方法。
伺服器端
打開伺服器項目MyGameServer,我們之前建立了一個ClientPeer的類,繼承自Photon.SocketServer.ClientPeer,實作了兩個方法進行用戶端請求的處理。
- OnOperationRequest——當成功接收到請求時調用
- OperationRequest operationRequest——封裝了請求的參數資訊,這個對象有兩個屬性需要關注,分别是
- operationRequest.OperationCode——區分請求
- operationRequest.Parameters——請求的參數,同樣是Dictionary<byte, System.Object>類型
- SendParameters sendParameters
- OperationRequest operationRequest——封裝了請求的參數資訊,這個對象有兩個屬性需要關注,分别是
- OnDisconnect——當斷開連接配接時調用
用戶端與伺服器互動流程
各位看官請看圖:
當用戶端Peer 調用OpCustom方法請求伺服器時,伺服器的PeerBase對象會接收到這個請求,OnOperationRequest便會執行,當伺服器處理資料後,可以對用戶端Peer進行響應,也可以不響應。如果需要響應用戶端Peer的話,需要在OnOperationRequest處理資料後調用SendOperationResponse方法進行響應。需要注意的是,用戶端Peer的OnOperationResponse隻用在Peer請求伺服器端後,伺服器在OnOperationRequest調用SendOperationResponse方法才會響應。可能會有點亂,簡單來說就是用戶端Peer需要得到響應的話就必須請求伺服器,并且伺服器在處理該條請求後響應用戶端OnOperationResponse才會被調用。
伺服器可以主動發送事件到用戶端,也就是通過SendEvent方法通知用戶端,這是用戶端的OnEvent便會被調用。
基礎原理就基本講完了,接下來就是寫代碼了。
程式設計部分
首先我們伺服器項目MyGameServer
在ClientPeer.cs的OnOperationRequest方法中進行log,判斷是否能進行送出請求到伺服器中
protected override void OnOperationRequest(Photon.SocketServer.OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters) {
//使用operationRequest.OperationCode區分請求
switch (operationRequest.OperationCode) {
case 1:
Main.log.Info("用戶端1請求伺服器");
//響應用戶端
//傳回用戶端的資料串
Dictionary<byte, object> response = new Dictionary<byte, object>();
//1為響應碼,這裡先使用123之類的作為辨別,後續将使用枚舉,使得其代表的含義清晰,易于解讀
OperationResponse op = new OperationResponse(1,response);
SendOperationResponse(op,sendParameters);
break;
default:
break;
}
}
打開Unity用戶端項目
建立Test.cs,請求伺服器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnGUI() {
if (GUI.Button(new Rect(20, 40, 100, 60), "向伺服器發送請求")) {
//請求參數
Dictionary<byte,System.Object> request = new Dictionary<byte,object>();
/**
* 第一個參數是請求操作碼
* 第二個參數是請求參數
* 第三個參數是否為穩定請求
* */
PhotonEngine.Peer.OpCustom(1, request, true);
}
}
}
PhotonEngine.cs中的OnOperationResponse方法進行log,檢視是否成功響應
public void OnOperationResponse(OperationResponse operationResponse) {
switch (operationResponse.OperationCode) {
case 1:
Dictionary<byte, System.Object> response = operationResponse.Parameters;
Debug.Log("從伺服器端傳回的資料是:");
break;
default:
break;
}
}
檢視結果
重新生成伺服器項目MyGameServer,重新啟動伺服器
用戶端成功請求伺服器,并且伺服器成功響應!
進行參數的傳遞
用戶端:
PhotonEngine.cs
public void OnOperationResponse(OperationResponse operationResponse) {
switch (operationResponse.OperationCode) {
case 1:
//使用operationResponse.Parameters獲得伺服器響應的資料串
Dictionary<byte, System.Object> response = operationResponse.Parameters;
object request ;
response.TryGetValue(1, out request);
Debug.Log("從伺服器端傳回的資料是:"+request);
break;
default:
break;
}
}
Test.cs
void OnGUI() {
if (GUI.Button(new Rect(20, 40, 100, 60), "向伺服器發送請求")) {
//請求參數
Dictionary<byte,System.Object> request = new Dictionary<byte,object>();
request.Add(1,100);
request.Add(2,"dfsajei短短釜底抽薪的23214");
/**
* 第一個參數是請求操作碼
* 第二個參數是請求參數
* 第三個參數是否為穩定請求
* */
PhotonEngine.Peer.OpCustom(1, request, true);
}
}
伺服器端:
Client.cs
//當用戶端成功連接配接伺服器時調用
protected override void OnOperationRequest(Photon.SocketServer.OperationRequest operationRequest, Photon.SocketServer.SendParameters sendParameters) {
//使用operationRequest.OperationCode區分請求
switch (operationRequest.OperationCode) {
case 1:
Main.log.Info("用戶端1請求伺服器");
Dictionary<byte,object> request = operationRequest.Parameters;
//解析參數
object intValue;
request.TryGetValue(1,out intValue);
object strValue;
request.TryGetValue(2,out strValue);
Main.log.Info("從用戶端1接收到的資料是:"+intValue+","+strValue);
//響應用戶端
Dictionary<byte, object> response = new Dictionary<byte, object>();
response.Add(1,"Success");
OperationResponse op = new OperationResponse(1,response);
SendOperationResponse(op,sendParameters);
break;
default:
break;
}
}
檢視結果
重新生成伺服器項目MyGameServer,重新啟動伺服器
用戶端成功發送資料到伺服器,并且伺服器成功響應!
好了,第四篇也結束了。這篇我們學習了如何請求伺服器并且響應用戶端。下篇我們将結合一個小的Demo進行更加詳細的學習如何開發一個Unity網絡遊戲。
ps:下篇預告,由于下篇用到了Mysql資料庫和NHibernate,請大家提前學習MySQL和NHibernate,至于NHibernate,學習過Hibernate的童鞋可以很快的上手,基本内容和Hibernate差不多,隻是配置檔案有些地方需要進行和.Net項目适應。關于NHibernate,大家可以參考
https://www.cnblogs.com/wanghaibin/p/5344320.html
感謝大家的支援。