1.Unity客户端与PhotonServer交互流程
本文主要针对Unity创建的客户端与基于PhotonServer创建的服务端交互进行进行简单示例说明。首先看一下二者发生交互的图解。
首先,当一个客户端向服务端发起请求,即通过PhotonPeer对象的OpCustom方法进行请求。此时,服务端的主类中CreatePeer函数被激活,告知服务端有一个客户端请求连接。然后,服务端的Photon.SocketServer.ClientPeer子类(即ClientPeer)中的函数OnOperationRequest开始处理客户端请求。此时,Server通过SendOperationResponse方法响应客户端,将反馈的结果发送给服务端。然后,客户端在IPhotonPeerListener实现类PhotonEngine的OnOperationResponse()方法中接收服务端反馈的结果。至此,一个请求响应操作完成。当客户端未请求时,服务端则在需要的方法通过PeerBase对象的SendEvent()方法,发送事件给客户端;客户端则通过IPhotonPeerListener实现类PhotonEngine的OnEvent()方法中接收服务端发过来的事件。了解流程之后下面看下一个基础示例。
2.Unity客户端与PhotonServer交互基础示例
首先,创建一个Unity客户端。项目名称为:PhotonServerClient.
(1)引入客户端的PhotonServer插件
创建一个Plugins文件夹,并将PhotonServerSDK文件下的lib文件中的Photon3Unity3D.dll拖拽到Plugins文件夹中。
(2)创建PhotonServer客户端实例类
主要实现IPhotonPeerListener接口。
PhotonEngine.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;//引入命名空间
public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {
private static PhotonEngine Instance;
private static PhotonPeer peer = null;
//客户端发消息给服务端 需要使用该属性
public static PhotonPeer Peer {
get {
return peer;
}
}
private void Awake()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(this.gameObject);
}
//跳转到第二个场景时,第一个场景的PhotonEngine Instance,
//需要将其删除掉,场景中只保留一个PhotonEngine Instance
//删除多余的PhotonEngine Instance
else if (Instance != null)
{
Destroy(this.gameObject);
return;
}
}
// Use this for initialization
void Start () {
//通过IPhotonPeerListener接收服务端反馈的结果
//peer需要定义Listener和协议
peer = new PhotonPeer(this,ConnectionProtocol.Udp);
//传入服务端的IP地址和端口号以及AppicationName
//要与PhotonServer.config,也就是服务端配置信息保持一致
peer.Connect("127.0.0.1:5055", "MyGame1");//连接服务端
}
// Update is called once per frame
void Update () {
//if (peer.PeerState == PeerStateValue.Connected)
//{
// peer.Service();//需要在Update里面一直调用该方法
//}
//不需要判断peer的状态
peer.Service();//需要在Update里面一直调用该方法
}
private void OnDestroy()
{
if (peer != null && peer.PeerState == PeerStateValue.Connected)
{
peer.Disconnect();//断开连接
}
}
public void DebugReturn(DebugLevel level, string message)
{
throw new System.NotImplementedException();
}
//客户端没有请求,服务端通知客户端时执行该函数
public void OnEvent(EventData eventData)
{
//eventData服务端传过来的数据
switch (eventData.Code)
{
case 1:
Debug.Log("Receive server response by OnEvent! opCode : 1");
//处理服务端传送过来的数据
Dictionary<byte, object> data = eventData.Parameters;
object intValue1, intValue2;
data.TryGetValue(1, out intValue1);
data.TryGetValue(2, out intValue2);
Debug.Log(intValue1.ToString() + intValue2.ToString());
break;
default:
break;
}
}
//客户端向服务端发起请求,服务端相应并返回结果时执行该函数
public void OnOperationResponse(OperationResponse operationResponse)
{
throw new System.NotImplementedException();
}
//peer有五种状态,一旦状态变化就会执行该函数
public void OnStatusChanged(StatusCode statusCode)
{
Debug.Log(statusCode);
}
}
客户端与服务端建立连接主要采用:PhotonPeer对象下的OpCustom方法来传输数据。以下用Test.cs来测试客户端向服务器发起请求,服务器作出反馈。客户端测试类:
Test.cs
using System;
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 () {
if (Input.GetMouseButton(0))
{
SendRequest();
}
}
private void SendRequest()
{
//OpCustom(byte customOpCode, Dictionary<byte, object> customOpParameters, bool sendReliable);
//customOpCode 为操作代码用于服务端区分这些请求 customOpParameters 传递给服务端的参数 sendReliable 是否建立可靠连接
Dictionary<byte, object> data = new Dictionary<byte, object>();
//数据通过字典的方式传输 一般在项目里面key不会单纯的用int类型来表示而是通过枚举类型
data.Add(1,100);
data.Add(2,"qweq数");
PhotonEngine.Peer.OpCustom(1,data,true);//发消息给客户端
}
}
服务器端处理客户端请求的代码应当在ClientPeer.OnOperationRequest()方法中实现。服务端具体代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
namespace MyGameServer
{
//管理每个客户端的连接(类似客服)
public class ClientPeer : Photon.SocketServer.ClientPeer
{
/*ClientPeer方法实现*/
/*OnDisconnect方法实现*/ //处理客户端断开连接的后续工作
//处理客户端的请求
protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
{
//通过客户端传过来的customOpCode区分请求
switch (operationRequest.OperationCode)
{
case 1:
//应当在MyGameServer.cs中,将log修改为public属性
MyGameServer.log.Info("Receive a client Request!");
//获取客户端传过来的参数
Dictionary<byte, object> data = operationRequest.Parameters;
object intValue;
data.TryGetValue(1,out intValue);
object stringValue;
data.TryGetValue(2,out stringValue);
MyGameServer.log.Info("Getting Parameters is " + intValue.ToString() + " " + stringValue);//输出在日志上
//与请求对应的,反馈给客户端也需要区分 与请求保持一致
OperationResponse opResponse = new OperationResponse(1);
//发送数据给客户端 opResponse.SetParameters()方法
Dictionary<byte, object> serverData = new Dictionary<byte, object>();
serverData.Add(1,111111);
serverData.Add(2,222222);
opResponse.SetParameters(serverData); //将服务端的数据发送给客户端
//响应客户端
SendOperationResponse(opResponse, sendParameters);
//客户端未请求时,服务端通知客户端 向客户端发送事件 通过SendEvent方式实现
EventData ed = new EventData(1);
ed.Parameters = serverData;
//SendEvent方法可以在服务器端的任何地方进行调用
SendEvent(ed,new SendParameters());
break;
case 2:
break;
default:
break;
}
}
}
}
与此对应的,客户端也需要处理服务端反馈的结果。此时,处理方法应当在PhotonEngine.OnOperationResponse()函数中实现,具体代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ExitGames.Client.Photon;//引入命名空间
public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {
/*中间代码,同上*/
//客户端向服务端发起请求,服务端相应并返回结果时执行该函数
public void OnOperationResponse(OperationResponse operationResponse)
{
//通过服务端的OperationResponse对象的OperationCode区分服务端的反馈
switch (operationResponse.OperationCode)
{
case 1:
Debug.Log("Receive server response! opCode : 1");
//处理服务端传送过来的数据
Dictionary<byte, object> data = operationResponse.Parameters;
object intValue1, intValue2;
data.TryGetValue(1,out intValue1);
data.TryGetValue(2, out intValue2);
Debug.Log(intValue1.ToString() + intValue2.ToString());
break;
case 2:
break;
default:
break;
}
}
}
3.程序运行截图
客户端运行截图:
服务端日志截图:
4.小结
本次示例主要讲解了基于PhotonServer与基于Unity客户端通信的基本操作。具体包括:客户端向服务端请求,服务端反馈客户端;以及,客户端未向服务端请求时,服务端通过发生事件的方式告知客户端。
另附:
Unity客户端源代码:https://github.com/ZSCXI/Unity/tree/master/PhotonServerClient_01
PhotonServer服务端源代码:https://github.com/ZSCXI/Visual_Studio_Projects/tree/master/PhotonServer