使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应

使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应

上一章我们完成了服务器与数据库的交互设计,下面我们开始第一个客户端与服务器的交互:注册请求

1、客户端的建立,建立unity工程-ILovePaoHuZi

建立2D工程ILovePaoHuZi,新建LoginScene场景。自行建立UI,UI部分这里就不讲解了,你们自己来做,我这里只讲解与服务器交互的部分.

1.1引入photon的DLL 文件

在unity工程中建立一个Plugins文件夹,之下再建立一个PhotonClient文件夹,将你的photon安装目录下的lib文件夹下的Photon3Unity3D.dll文件放进去,这样就可以在脚本中引用它了。

1.2 建立PhotonClientManager

     我们的游戏需要有一个脚本专门负责处理与服务器之间的通讯与交互。在场景中建立一个叫做PhotonClientManager的空物体,再其上建立一个叫做PhotonClientManager脚本。脚本引用上面导入的Photon3Unity3D.dll文件(using ExitGames.Client.Photon;),然后继承它里面的IPhotonPeerListener接口并实现接口,这样客户端的管理脚本就建立好了。

    然后在Awake方法中将此脚本单列化,并设置后台运行、切换场景不删除等必须配置。

    再建立一个与服务器交互的photon的peer,并定义你的服务器地址以及端口号,以及服务器的名字,这些定义的变量需要与你服务器设置相同。

    最后在update中添加peer发送请求的命令if (peer != null) peer.Service();,代表每帧都会检查一次peer是否有请求要发送,如果有就会发送给服务器,完成后代码如下:

using UnityEngine;
using System.Collections;
using ExitGames.Client.Photon;
using System;

public class PhotonClientManager : MonoBehaviour, IPhotonPeerListener
{
    #region 变量定义

    #region 定义photon客户端设置需要的变量

    /// 
    /// PhotonClientManager的单列模式
    /// 
    public static PhotonClientManager s_PhotonClientManager;
    /// 
    /// 连接PHTON服务器用的 连接工具
    /// 
    private PhotonPeer peer;
    /// 
    /// 连接工具PhotonPeer 使用的协议
    /// 
    public ConnectionProtocol 连接协议 = ConnectionProtocol.Tcp;
    /// 
    /// 连接工具PhotonPeer 要连接的IP地址和端口号
    /// 
    public string SeverIpAdress = "127.0.0.1:4530";
    /// 
    /// 连接工具PhotonPeer 要连接的服务器名字
    /// 
    public string SeverName = "ILovePaoHuZi";


    #endregion


    #endregion


    #region MonoBehaviour脚本原生方法
    void Awake()
    {
        //创建单列模式
        //如果单列模式还没有设置,则让这个脚本成为单列模式,如果存在,则删除这个脚本以及物体
        if (s_PhotonClientManager == null)
        {
        s_PhotonClientManager = this;
        }
        else
        {
            Destroy(this.transform);
        }
        //设置脚本属性,换场景不删除、后台运行等
        DontDestroyOnLoad(this.transform);
        Application.runInBackground = true;

        //建立PhotonPeer实例(第一个参数为带有IPhotonPeerListener的脚本(通讯监听类的实例),第2个为选用的通讯协议);
        peer = new PhotonPeer(this, 连接协议);
        //连接器 将要连接的服务器IP端口加上服务器名字
        peer.Connect(SeverIpAdress, SeverName);
        //连接器 开始发送队列中拥有的 通讯信息,所有固话请求以及通讯请求都以队列的方式存储在连接器中,当执行peer.Service()方法时才对服务器发送他们


    }

    void Start()
    {

    }

   
    void Update()
    {
        //每帧检查peer中是否有命令需要发送,当peer有命令时,开始发送请求
        if (peer != null) peer.Service();
    }

    #endregion

    #region photon接口方法

    //当photonclient要输出debug时,会调用此方法
    public void DebugReturn(DebugLevel level, string message)
    {
        
    }
    //当发送event事件时会调用此方法
    public void OnEvent(EventData eventData)
    {
        
    }
    //当收到服务器的响应时,会调用此方法
    public void OnOperationResponse(OperationResponse operationResponse)
    {
        
    }
    //当客户端状态改变时会调用此方法
    public void OnStatusChanged(StatusCode statusCode)
    {
       
    }

    #endregion
   
}

1.3建立请求类型处理模型

我们的游戏的通讯系统需要设计一个处理模型来规范化处理流程:

使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应_第1张图片

这是我准备使用的结构,里面有个需要我们去建立,

第一:是各种请求的处理脚本,我准备一种请求一个脚本,这样方便管理。例如:登录,注册、开游戏房、开始游戏、新加入玩家、游戏结束等等。

第二:是类型判断,我准备采用字典的形式将类型与处理脚本联系起来,当收到信息后,直接可以在字典内查到要使用的处理脚本,然后直接由其处理就好了。

那么,现在我们需要建立的就是类型,而且要求在服务器和客户端上的类型都是一样的,我们可以采用枚举类型进行划分。而photon的通讯信息的类型是由byte格式来区分的,那么我们建立一个通讯类型枚举(byte型)在ILovePaoHuZiCommon工程中,还记得这个工程吗?他在我们photon服务器解决方案中,他是用来存储服务器与客户端共用的一些类的。

1.4建立服务器与客户端共用的通讯类型枚举

使用VS打开我们的photon服务器解决方案-ILovePaoHuZi.在ILovePaoHuZiCommon工程中添加一个叫做通讯类型枚举的类文件。将其改成枚举byte类型,并添加2个项目,注册请求_通讯类型和登录请求_通讯类型。代码如下:

namespace ILovePaoHuZiCommon
{
    public enum 通讯类型枚举:byte
    {
        注册请求_通讯类型,
        登录请求_通讯类型
        
    }
}
然后对整个解决方案进行生成, 注意:因为unity的mono最高只支持3.5版本的.NET,所以要修改ILovePaoHuZiCommon的目标框架为.net3.5,然后在重新生成,否则unity引用ILovePaoHuZiCommon时候会报错
然后到你生成的 Photon安装路径\deploy\ILovePaoHuZi文件夹内找到ILovePaoHuZiCommon.dll文件,将他复制放入unity工程的Plugins\PhotonClient目录下,以后我们可以引用它;

使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应_第2张图片

1.5、在PhotonClientManager 上建立发送注册请求方法:

发送注册请求方法可以建立在任何脚本上,只是为了方便管理才放入这里;但是,将通讯信息是必须通过PhotonClientManager脚本中的peer来发送的,所以我们必须在PhotonClientManager脚本中建立一个发送通讯请求的方法,方便所有的处理器对其调用,并发送请求:

A:PhotonClientManager上建立发送通讯请求方法:

 public void 发送通讯请求(通讯类型枚举 _通讯类型枚举,Dictionary 要发送的内容,bool 是否需要保证传输到位)
    {
        peer.OpCustom((byte)_通讯类型枚举, 要发送的内容, 是否需要保证传输到位);
    }
这里解释下,bool 是否需要保证传输到位,是代表photon是不是要保证这个信息被对方接收,如果为ture的话,服务器会确认收到,如果信息在途中丢失,客户端会再次发送这个信息,如果为false的话,客户端只管发出去,不管服务器是否接收的到,对于很多信息例如:死亡、开房等等主要信息,必须保证服务器收到,而位置信息,聊天信息可以不确认。当然你也可以全部为ture,但是如果某个信息卡住了,会导致一些游戏表现上的问题,例如位置信息,因为有时间序列的要求,如果1分钟前的信息被卡住了,然后再次发送后,你会突然发现你的人物突然又回到1分钟前的位置。

peer.OpCustom就是photon构建通讯信息的方法,他发送的内容我们叫做请求参数,这个参数必须是一个字典,而且必须是byte为key的字典,而字典的值可以是任何东西,类、数字、数组、甚至是一个list.所以我们需要把 参数这个字典的byte也要做一个枚举,好到了服务器或者客户端能够让他知道字典的值到底是啥,然后通过正确的转换就可以的到传输的东西。

B:建立 通讯内容参数类型枚举

因为这个枚举是服务器与客户端共用的,所以又要回到服务器端的ILovePaoHuZiCommon工程中添加这个枚举,并重新生成它,然后unity重新导入最新的ILovePaoHuZiCommon.dll文件:

namespace ILovePaoHuZiCommon
{
    public enum 通讯内容_参数枚举:byte
    {
        UserInfo_Model类,
        Image_Model类
    }
}
C:在PhotonClientManager脚本上建立注册方法

我们在注册的时候需要将一个完整的UserInfo_Model类传输给服务器,但是photon并不支持直接传送自定义类,那么我们可以想办法将这个类转换为string的形式传送过去,这里我们就需要一个 数据交换格式 来转换它为string,这里我们使用LitJson,我们可以在Json的官网获得它,地址是http://www.json.org,然后找到C#里面的LitJson,下载它并且将其放在unity工程中的Plugins-PhotonClient文件夹下,并且引用它:

以后要注册新用户的话可以直接调用它来发送注册申请

public void 注册用户(string _用户名, string _密码, string _昵称, string _省名, string _市, string _县区)
    {
        UserInfo_Model 欲注册的用户信息 = new UserInfo_Model();
        欲注册的用户信息.用户名 = _用户名;
        欲注册的用户信息.密码 = _密码;
        欲注册的用户信息.昵称 = _昵称;
        欲注册的用户信息.省名 = _省名;
        欲注册的用户信息.市 = _市;
        欲注册的用户信息.县区 = _县区;

        //将 UserInfo_Model 类格式 通过 LitJson数据交换格式 转换为string
        string 内容信息 = JsonMapper.ToJson(欲注册的用户信息);

        //生成要附带的数据字典
        Dictionary 要传送的内容 = new Dictionary();
        要传送的内容.Add((byte)通讯内容_参数枚举.UserInfo_Model类, 内容信息);

        //将字典和通讯类型代码使用PhotonClientManager发送出去
        PhotonClientManager.s_PhotonClientManager.发送通讯请求(通讯类型枚举.注册请求_通讯类型, 要传送的内容, true);
        
    }



2、服务器上建立注册响应方法

2.1、在服务器上建立handler_base和handler_注册请求;

要使用字典进行类型判断并直接使用字典类储存的处理脚本对通讯进行处理,那么我们为了将处理脚本装入字典,就需要一个定义一个处理脚本基类。然后我们以它为父类继承它建立各种类型的处理脚本,这样就可以装入字典了。

这2个类文件代码如下,我们在ILovePaoHuZi工程下新建立一个文件夹Handler专门用来放通讯处理脚本;handler_base代码如下,它是作为通讯处理器的基类:

using Photon.SocketServer;

namespace ILovePaoHuZi.Handler
{
    public abstract  class Handler_base
    {
        public abstract OperationResponse 收到需要处理的信息(OperationRequest 客户端发来的请求Request);

    }
}
而建立 handler_注册请求之前我们还需要在ILovePaoHuZiCommon工程中建立一个新的枚举,它表示了服务器返回给客户端的简单响应,例如,成功,失败,错误等结果。在ILovePaoHuZiCommon中新建一个类文件 服务器返回码枚举 。代码如下:

namespace ILovePaoHuZiCommon
{
   public enum 服务器返回码枚举 :byte
    {
        成功,
        失败,
        服务器错误
    }
}
有了这个返回码,我们的一些简单请求就直接在响应信息中带上就可以了。

然后建立 handler_注册请求 类文件,放入ILovePaoHuZi工程下Handler文件夹代码如下(注意:要在服务器ILovePaoHuZi工程中引用LitJson作为数据交换格式,将信息中的string还原为UserInfo_Model类)

using ILovePaoHuZiCommon.model;
using ILovePaoHuZiCommon;
using Photon.SocketServer;
using ExitGames.Logging;
using ILovePaoHuZi.DB.DBManager;
using LitJson;

namespace ILovePaoHuZi.Handler
{
    public class Handler_注册请求 : Handler_base
    {
        /// 
        /// LOG接口
        /// 
        private static readonly ILogger log = ExitGames.Logging.LogManager.GetCurrentClassLogger();
        /// 
        /// 数据库操作脚本
        /// 
        UserInfo_Manager UserInfo类_数据库管理器;

        //编写一个构造函数,在new这个脚本的时候执行一些指令
        public Handler_注册请求(){
            //在这个通讯处理器被实例化时,建立一个数据库管理器,专门为这个 通讯处理器 服务
            UserInfo类_数据库管理器 = new UserInfo_Manager();
            }

        public override OperationResponse 收到需要处理的信息(OperationRequest 客户端发来的请求Request)
        {
            //获取传输过来的内容中的UserInfo_Model
            object 传来的内容;

            客户端发来的请求Request.Parameters.TryGetValue((byte)通讯内容_参数枚举.UserInfo_Model类,out 传来的内容);

            //通过 数据交换格式 LitJson将客户端传递过来的string内容转换为UserInfo_Model
            

            UserInfo_Model 传来的注册信息 = JsonMapper.ToObject(传来的内容.ToString());
            //调用数据库操作脚本的新建用户方法
            int 数据库操作结果=   UserInfo类_数据库管理器.用户注册(传来的注册信息);
            //根据调用数据库返回来的代码选择服务器响应的内容和代码
            if (数据库操作结果 == -1)
            {//返回为-1时,代表用户名有相同的用户,注册失败
                OperationResponse 服务器的响应 = new OperationResponse();
                服务器的响应.OperationCode = (byte)通讯类型枚举.注册请求_通讯类型;
                服务器的响应.ReturnCode =(byte) 服务器返回码枚举.失败;
                服务器的响应.DebugMessage = "用户名被占用";
                return 服务器的响应;
            }
            if (数据库操作结果 == -2)
            {//返回为-2时,代表有错误发生
                OperationResponse 服务器的响应 = new OperationResponse();
                服务器的响应.OperationCode = (byte)通讯类型枚举.注册请求_通讯类型;
                服务器的响应.ReturnCode = (byte)服务器返回码枚举.服务器错误;
                服务器的响应.DebugMessage = "服务器未知错误";
                return 服务器的响应;
            }
            if (数据库操作结果 >= 0)
            {//返回为>=0时,代表注册成功,新用户ID为返回码
                OperationResponse 服务器的响应 = new OperationResponse();
                服务器的响应.OperationCode = (byte)通讯类型枚举.注册请求_通讯类型;
                服务器的响应.ReturnCode = (byte)服务器返回码枚举.成功;
                //注册成功,将注册产生的用户ID返回给客户端
                服务器的响应.DebugMessage = 数据库操作结果.ToString();
                return 服务器的响应;
            }

            return null;
        }
    }
}


2.1、在服务器上MainClass上建立通讯处理器字典以及每个通讯处理器注册的方法。

2.1.A、先将MainClass定义为单列模式,方便其他脚本的访问:

 public static MainClass s_MainClass;
并在Setup()方法中添加赋值语句:

      //服务器启动成功的时候会调用这个方法
        protected override void Setup()
        {
            s_MainClass = this;
            InitLogging();
            log.Debug("服务器启动");
        }
2.1.B、定义 通讯处理器字典,好让其他脚本根据 信息内容中的 通讯类型枚举 调用它选择 通讯处理脚本(Handler脚本)

 public Dictionary 通讯处理器字典 = new Dictionary();
2.1.C、添加通讯处理器(Handler脚本)的注册方法,将其添加进字典,记住,每编写一个通讯处理器就需要在这个方法中将其添加进字典(这里和客户端不一样,因为客户端是挂载在场景上,会自动运行,所以就自动添加了,而在服务器上只能手动实例化它并手动添加进字典)。
//每编写一个通讯类型处理器,必须将其添加进字典进行注册。
        public void 通讯处理器注册方法()
        {
            通讯处理器字典.Add((byte)通讯类型枚举.注册请求_通讯类型, new Handler_注册请求());
        }
2.1.d、完成后,MainClass的代码:

using ExitGames.Logging;
using ExitGames.Logging.Log4Net;
using ILovePaoHuZi.Handler;
using log4net;
using log4net.Config;
using Photon.SocketServer;
using System.Collections.Generic;
using System.IO;
using ILovePaoHuZiCommon;

namespace ILovePaoHuZi
{
    public class MainClass : ApplicationBase
    {
        #region 定义变量
        public static MainClass s_MainClass;
        public Dictionary 通讯处理器字典 = new Dictionary();
        private static readonly ILogger log = ExitGames.Logging.LogManager.GetCurrentClassLogger();

        #endregion

        #region 其他方法
        //每编写一个通讯类型处理器,必须将其添加进字典进行注册。
        public void 通讯处理器注册方法()
        {
            通讯处理器字典.Add((byte)通讯类型枚举.注册请求_通讯类型, new Handler_注册请求());
        }

        #endregion

        #region photon接口方法
        //当有客户端连接上服务器时,将引用这个方法,建立一个客户端处理类,我们叫它ClientPeer,他是一个继承自PeerBase的自定义类
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {
            客户端Peer temp = new 客户端Peer(initRequest);
            return temp;
        }
        //服务器启动成功的时候会调用这个方法
        protected override void Setup()
        {
            s_MainClass = this;
            InitLogging();
            log.Debug("服务器启动");
        }
        //服务器停止的时候会调用这个方法
        protected override void TearDown()
        {
            log.Debug("服务器停止");
            
        }
        //设置Log文件
        protected virtual void InitLogging()
        {
            ExitGames.Logging.LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);
            //这里是设置Log文件储存的路径,一般不用改了
            GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(this.ApplicationRootPath, "log");
            //将这里的"MS"改成"ILovePaoHuZi"
            GlobalContext.Properties["LogFileName"] = "ILovePaoHuZi" + this.ApplicationName;
            //注意,这里有一个log4net.config配置文件需要拷贝到工程里面来,并且要设置其输出时为拷贝
            //这个文件位于Photon安装路径\src-server\Loadbalancing\Loadbalancing文件下,
            //复制进工程后,点击它选择属性-高级-复制到输出目录这一项,原来是不复制,改成始终复制
            XmlConfigurator.ConfigureAndWatch(new FileInfo(Path.Combine(this.BinaryPath, "log4net.config")));
        }

        #endregion
    }
}

2.3、服务器接收信息并响应信息

    还记得 客户端Peer 这个类文件吗?一个服务器会有很多个这个脚本在运行,它是服务器上专门用来处理客户端信息的类文件,每一个连接上的客户端都会有一个对应的 客户端Peer  类,它拥有几个接口,所以当客户端的信息传到服务器的时候,第一时间是传到它的OnOperationRequest()方法中,我们需要在这里对信息进行解析,以决定采用的响应。
代码如下,解释在代码中:

using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
using ExitGames.Logging;
using ILovePaoHuZi.Handler;

namespace ILovePaoHuZi
{
    class 客户端Peer : ClientPeer
    {
        private static readonly ILogger log = ExitGames.Logging.LogManager.GetCurrentClassLogger();
        //这个自定义类的构造方法,因为他的父类同样需要参数构造,所以加上base(initRequest)
        public 客户端Peer(InitRequest initRequest):base(initRequest){
            
        }
        //当客户端断线的时候调用的方法
        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
           
        }

        //当服务器收到来自这个客户端的请求的时候的方法
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {

            Handler_base 选定的通讯处理器;
            //先检查字典,看看这个通讯类型是否有处理器进行处理
          if( ! MainClass.s_MainClass.通讯处理器字典.TryGetValue(operationRequest.OperationCode, out 选定的通讯处理器))
            {
                //没有这个通讯类型,代表通讯信息代码错误或者通讯处理器没有注册
                log.Debug("未知的通讯类型:"+ operationRequest.OperationCode.ToString());
                return;
            }
           //根据字典选用 通讯处理器 进行处理,并获得返回的 响应
            OperationResponse 服务器的响应= 选定的通讯处理器.收到需要处理的信息(operationRequest);
            if (服务器的响应 != null)
            {//代表 正确的从 通讯处理器 获得了服务器响应,那么我们返回它给客户端
                SendOperationResponse(服务器的响应, sendParameters);
            }

        }
    }
}

3、客户端收到服务器响应后的处理。

好了,上面的工作完成了客户端发送注册请求,服务器收到注册请求并操作数据库进行工作,然后返回一个响应信息给客户端,下面我们就需要编写在客户端接收服务器响应后的处理方法了;前面我们说过,我们的客户端接收到服务器的信息是在PhotonClientManager类文件的OnOperationResponse()方法中,在这个方法中我们根据服务器返回的信息代码按照字典去选择通讯处理器完成动作;

3.1、建立客户端通讯处理字典

要使用字典进行类型判断并直接使用字典类储存的处理脚本对通讯进行处理,那么我们为了将处理脚本装入字典,就需要一个定义一个处理脚本类型。然后我们以它为父类继承它建立各种类型的处理脚本,这样就可以装入字典了。当然,你可以可以使用if(通讯类型==XX)使用XX处理请求脚本的方式来实现。不过,当今后通讯类型多了的话,你不要忘记每个类型都要增加一个判断语句哦!

3.1.A、我们建立一个处理脚本的基础类-Handler_Base,将他放置到Scripts-PhotonClient-Handles文件夹下,以后的通讯处理器全放这里,Handler_Base要设置成抽象类,并且继承MonoBehaviour,要定义一个抽象函数用来定义子类的通讯类型,还要定义一个virtual虚拟start方法,让他自动向PhotonClientManager的单列模式的字典进行注册;这样我们今后建立的新处理脚本会自动将自己和自己的类型在PhotonClientManager的字典中注册好;然后建立一个抽象方法-进行信息处理(OperationResponse 服务器的响应信息),用来接收由PhotonClientManager传入的来自服务器的通讯信息;代码如下:

using UnityEngine;
using ILovePaoHuZiCommon;
using System.Collections;
using ExitGames.Client.Photon;

public abstract class Handler_Base:MonoBehaviour  {

    public abstract 通讯类型枚举 本脚本通讯类型 { get; }
    public virtual void  Start()
    {
        //PhotonClientManager中的字典还未建立,所以暂时空着把
    }
    public abstract void 进行信息处理(OperationResponse 服务器的响应信息);
}

3.1.B、在PhotonClientManager中建立 通讯处理字典 并编写注册方法;

下面我们回到PhotonClientManager中,定义一个字典名字叫做 通讯类型处理器字典,

    #region 其他定义

    /// 
    /// 储存有通讯类型和应该采用的处理器的字典。通过他来自动选择不同的处理器处理不同类型的通讯类型信息
    /// 
   public Dictionary 通讯类型处理器字典 = new Dictionary();

    #endregion
并添加注册方法
  #region 其他方法

    public void 注册通讯类型处理器(通讯类型枚举 _通讯类型, Handler_Base _具体的通讯处理器脚本)
    {
        通讯类型处理器字典.Add((byte)_通讯类型, _具体的通讯处理器脚本);
    }

    #endregion

3.1.C、在Handler_Base中添加注册方法

下面我们再回到Handler_Base中,在start方法中添加注册的命令;

using UnityEngine;
using ILovePaoHuZiCommon;
using System.Collections;
using ExitGames.Client.Photon;

public abstract class Handler_Base:MonoBehaviour  {

    public abstract 通讯类型枚举 本脚本通讯类型 { get; }
    public virtual void  Start()
    {
        PhotonClientManager.s_PhotonClientManager.注册通讯类型处理器(本脚本通讯类型,this);
    }
    public abstract void 进行信息处理(OperationResponse 服务器的响应信息);
}

3.2、建立客户端上的第一个通讯处理器-注册请求处理器

先解释一下,因为我们的Handler_Base中继承MonoBehaviour需要用到start()方法,所有我们的具体的通讯处理器都需要挂载在场景中的物体上,他才会工作并自动注册。所以,我们在场景中的PhotonClientManager空物体下再建立一个空物体-handleList,专门用来挂载各种通讯处理器;

3.2.1、建立注册请求处理器-Handler_注册请求

在场景的PhotonClientManager-handleList上新建一个叫做 Handler_注册请求 的脚本,让其继承自Handler_Base,实现抽象方法,重写start()方法,记住start方法中的base.Start()不要删除。代码如下:

using ExitGames.Client.Photon;
using ILovePaoHuZiCommon;

public class Handler_注册请求 : Handler_Base
{
    public override 通讯类型枚举 本脚本通讯类型
    {
        get
        {
            //这个脚本是处理哪种通讯类型的就return 哪种通讯类型
            return 通讯类型枚举.注册请求_通讯类型;
        }
    }

    public override void Start()
    {
        base.Start();
        //这后面还可以添加你需要的代码,但是不能删除base.Start();

    }
    //这个方法是用来接收由PhotonClientManager传递的来自服务器的通讯信息的方法
    public override void 进行信息处理(OperationResponse 服务器的响应信息)
    {
       
    }
}


3.2.2、刚刚我们在服务器上又建立了一个返回码的枚举,所以我们要重新生成ILovePaoHuZiCommon.dll并导入最新版本的文件到unity客户端上

3.3、在PhotonClientManager的OnOperationResponse中分拣服务器响应信息,并指派 通讯处理器字典中相对应的处理器类进行处理

 public void OnOperationResponse(OperationResponse operationResponse)
    {
       Handler_Base 选择的处理器脚本;
      if( !通讯类型处理器字典.TryGetValue(operationResponse.OperationCode, out 选择的处理器脚本))
        {
            Debug.Log("未知的服务器响应通讯类型:" + operationResponse.OperationCode.ToString());
        }
        选择的处理器脚本.进行信息处理(operationResponse);

    }

好了,这里已经完成分拣工作,如果是注册的通讯类型,那么就会选择我们刚刚建立的Handler_注册请求 脚本来处理。

3.4、 Handler_注册请求的信息处理;
好了,现在服务器的响应信息已经传到了  Handler_注册请求 脚本的 进行信息处理(OperationResponse 服务器的响应信息) 方法中了,下面我们就编写根据服务器反馈采用的行为,UI_注册.s_UI_注册.注册成功()这些方法是我的处理方法,你要怎么做你自己写就好了;

public override void 进行信息处理(OperationResponse 服务器的响应信息)
    {

        switch (服务器的响应信息.ReturnCode)
        {
            case (byte)服务器返回码枚举.成功:
                {//如果服务器返回为成功
                    UI_注册.s_UI_注册.注册成功();
                    break;
                }
            case (byte)服务器返回码枚举.失败:
                {//如果服务器返回为失败
                    UI_注册.s_UI_注册.注册失败(服务器的响应信息.DebugMessage);
                    break;
                }
            case (byte)服务器返回码枚举.服务器错误:
                {//如果服务器返回为错误
                    UI_注册.s_UI_注册.注册失败(服务器的响应信息.DebugMessage);
                    break;
                }
        }

    }


好了,最后在电脑-管理中打开数据库的服务,然后启动photonserver,然后运行unity,注册一个用户试试。OK,反正我的测试正常了,你的呢?
如果有问题请联系我微信:hmokhmok

后面的登录什么什么的请求都可以自己按照结构写了;客户端的结构和服务器的数据结构我会做个图发上来。

使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应_第3张图片

使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应_第4张图片


你可能感兴趣的:(使用PhotonServer和Unity建立一个棋牌类游戏实例(三)Unity客户端的注册请求和服务器的注册请求响应)