PhotonServer(四)Unity客戶端連接服務(wù)器實(shí)現(xiàn)登陸值纱、注冊(cè)

首先我們?cè)趗nity客戶端里面先創(chuàng)建好我們的登陸UI界面嗎寂呛,一個(gè)是登陸界面LoginPanel,一個(gè)是注冊(cè)界面RegisterPanel伦籍,點(diǎn)擊注冊(cè)跳轉(zhuǎn)到注冊(cè)界面這么我就不說(shuō)了蓝晒,這里我只講解下實(shí)現(xiàn)點(diǎn)擊登陸發(fā)送請(qǐng)求給服務(wù)器然后服務(wù)器進(jìn)行驗(yàn)證并回應(yīng)給客戶端,實(shí)現(xiàn)點(diǎn)擊確認(rèn)注冊(cè)發(fā)送添加數(shù)據(jù)的請(qǐng)求并回應(yīng)給客戶端這兩個(gè)按鈕帖鸦。

Paste_Image.png
這里的客戶端我還是用PhotonServer(二)創(chuàng)建unity客戶端里面的客戶端芝薇,有不懂的可自行去了解.這里我把上次測(cè)試的PhotonText腳本取消了,這里不需要作儿。
Paste_Image.png

下面開始做請(qǐng)求的發(fā)送了洛二。首先我們先大概的框架架構(gòu)好,先在unity客戶端里面創(chuàng)建一個(gè)總的請(qǐng)求類Request腳本攻锰,定義為抽象類繼承自MonoBehaviour晾嘶,然后再創(chuàng)建一個(gè)登陸請(qǐng)求的LoginRequest腳本和一個(gè)注冊(cè)請(qǐng)求的RegisterRequest腳本,讓這兩個(gè)請(qǐng)求都繼承自這個(gè)Request抽象類娶吞。然后讓這兩個(gè)請(qǐng)求腳本分別掛在載各自的登陸面板和注冊(cè)面板上垒迂。這時(shí)候請(qǐng)求的腳本創(chuàng)建好后就需要?jiǎng)?chuàng)建處理UI的腳本了。這時(shí)候再在各自的面板上創(chuàng)建處理UI的腳本妒蛇,我在LoginPanel面板上創(chuàng)建Loginpanel腳本在RegisterPanel面包上創(chuàng)建RegistrerPanel腳本這時(shí)候大概的一些腳本框架出來(lái)了
Paste_Image.png
下面開始寫入代碼机断,首先我們?cè)赗equest腳本中需要兩個(gè)總的方法讓LoginRequest和RegisterRequest去實(shí)現(xiàn)楷拳。

using UnityEngine;
using ExitGames.Client.Photon;

public  abstract class Request:MonoBehaviour  {
      public   abstract void DefaultRequse();//向服務(wù)器發(fā)起請(qǐng)求方法
      public   abstract void OnOperationResponse(OperationResponse operationResponse);//服務(wù)器收到消息響應(yīng)給客戶端的方法
}

然后去繼承這個(gè)抽象類的兩個(gè)腳本LoginRequest和RegisterRequest腳本里面實(shí)現(xiàn)著兩個(gè)方法,然后其實(shí)我們知道響應(yīng)的方法其實(shí)是在PhotonEngine腳本里面處理的,那么我們?cè)趺醋屵@個(gè)響應(yīng)調(diào)用到我們的Request方法里面呢,這時(shí)候我們就需要對(duì)這些Request做一些區(qū)分吏奸,那怎么去區(qū)分這些Request欢揖,我們每一個(gè)請(qǐng)求都對(duì)應(yīng)一個(gè)OperationCode,所以要給沒一個(gè)Request定義一個(gè)變量OperationCode苦丁,在我PhotonServer(二)的時(shí)候也提到了OperationCode表示發(fā)起請(qǐng)求的編號(hào)浸颓,接收的時(shí)候便于找到物臂,這個(gè)編號(hào)我看可以用去定義枚舉來(lái)實(shí)現(xiàn)旺拉。那么我們?cè)?strong>服務(wù)器端新建一個(gè)項(xiàng)目命名為Common,添加幾個(gè)類分別命名為ReturnCode、ParameterCode棵磷、OperationCode蛾狗、EventCode,寫入的枚舉分別為以下

Paste_Image.png

namespace Common
{
    public  enum ReturnCode:short//區(qū)分請(qǐng)求返回值仪媒,成功或者失敗
    {
        Success,
        Failed
    }
}

namespace Common
{
    public enum ParameterCode:byte//區(qū)分傳送數(shù)據(jù)時(shí)候參數(shù)的類型
    {
        Username,
        Password
    }
}
namespace Common
{
    public enum OperationCode:byte//區(qū)分請(qǐng)求和響應(yīng)的類型
    {
        Login,
        Register,
        Default
    }
}
namespace Common
{
    public  enum EventCode :byte//區(qū)分服務(wù)器向客戶端發(fā)送的事件的類型
    {
      //暫時(shí)不定義
    }
}

然后再服務(wù)器MyGameServer里面添加引用選擇項(xiàng)目把我剛剛創(chuàng)建的Common項(xiàng)目添加進(jìn)來(lái)沉桌,然后把MyGameServer重新生成下。


Paste_Image.png

然后可以在我們的文件夾里面找到Common.dll算吩,把這個(gè)dll導(dǎo)入到我們的unity的Plugins文件夾里面.


Paste_Image.png
然后繼續(xù)客戶端的操作打開Request腳本留凭,這時(shí)候我們就可以定義一個(gè)OperationCode字段了
using Common;
using ExitGames.Client.Photon;
using UnityEngine;

public  abstract class Request:MonoBehaviour  {

     public  OperationCode OpCode;
    
     public   abstract void DefaultRequse();//向服務(wù)器發(fā)起請(qǐng)求方法
     public   abstract void OnOperationResponse(OperationResponse operationResponse);//服務(wù)器收到消息響應(yīng)給客戶端的方法

然后就可以去指定相應(yīng)的OperationCode了


Paste_Image.png

這時(shí)候我們就需要用代碼去關(guān)聯(lián)OnOperationResponse響應(yīng)到Request了。首先PhotonEngine里面的代碼

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

public class PhotonEngine : MonoBehaviour,IPhotonPeerListener {

    public  static PhotonEngine Instance;
    public static PhotonPeer Peer//讓外界可以訪問我們的PhotonPeer
    {
        get
          {
            return peer;
           }
        }
    //創(chuàng)建一個(gè)字典偎巢,根據(jù)OperationCode去找到所有相對(duì)應(yīng)的Request對(duì)象
    private Dictionary<OperationCode, Request> RequestDict = new Dictionary<OperationCode, Request>();

    private  static PhotonPeer peer;
    private void Awake()
    {
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(this.gameObject);
        }else if (Instance != this)
        {
            Destroy(this.gameObject);return;
        }
    }

    // Use this for initialization
    void Start () {
        //連接服務(wù)器端
        //通過Listender連接服務(wù)器端的響應(yīng)
        //第一個(gè)參數(shù) 指定一個(gè)Licensed(監(jiān)聽器) ,第二個(gè)參數(shù)使用什么協(xié)議
         peer = new PhotonPeer(this,ConnectionProtocol.Udp);
        //連接 UDP的 Ip地址:端口號(hào)蔼夜,Application的名字
        peer.Connect("127.0.0.1:5055", "MyGame1");
        
    }
    
    // Update is called once per frame
    void Update () {
      
            peer.Service();//需要一直調(diào)用Service方法,時(shí)時(shí)處理跟服務(wù)器端的連接
    }
    //當(dāng)游戲關(guān)閉的時(shí)候(停止運(yùn)行)調(diào)用OnDestroy
    private void OnDestroy()
    {
        //如果peer不等于空并且狀態(tài)為正在連接
        if (peer != null && peer.PeerState == PeerStateValue.Connected)
        {
            peer.Disconnect();//斷開連接
        }
    }

    //
    public void DebugReturn(DebugLevel level, string message)
    {
     
    }
    //如果客戶端沒有發(fā)起請(qǐng)求,但是服務(wù)器端向客戶端通知一些事情的時(shí)候就會(huì)通過OnEvent來(lái)進(jìn)行響應(yīng) 
    public void OnEvent(EventData eventData)
    {


    }
    //當(dāng)我們?cè)诳蛻舳讼蚍?wù)器端發(fā)起請(qǐng)求后压昼,服務(wù)器端接受處理這個(gè)請(qǐng)求給客戶端一個(gè)響應(yīng)就會(huì)在這個(gè)方法里進(jìn)行處理
    public void OnOperationResponse(OperationResponse operationResponse)
    {
        OperationCode opCode = (OperationCode)operationResponse.OperationCode;//得到響應(yīng)的OperationCode
        Request request = null;
        bool temp = RequestDict.TryGetValue(opCode, out request);//是否得到這個(gè)響應(yīng)
       // 如果得到這個(gè)響應(yīng)
        if (temp)
        {
            request.OnOperationResponse(operationResponse);//處理Request里面的響應(yīng)
        }
        else
        {
            Debug.Log("沒有找到對(duì)應(yīng)的響應(yīng)處理對(duì)象");
        }
    }
    //如果連接狀態(tài)發(fā)生改變的時(shí)候就會(huì)觸發(fā)這個(gè)方法求冷。
    //連接狀態(tài)有五種,正在連接中(PeerStateValue.Connecting)窍霞,已經(jīng)連接上(PeerStateValue.Connected)匠题,正在斷開連接中( PeerStateValue.Disconnecting),已經(jīng)斷開連接(PeerStateValue.Disconnected)但金,正在進(jìn)行初始化(PeerStateValue.InitializingApplication)
    public void OnStatusChanged(StatusCode statusCode) { 
    
    }

    //添加Requst
    public void AddRequst(Request requst)
    {
    RequestDict.Add(requst.OpCode, requst);

    }
    //移除Requst
    public void RemoveRequst(Request request)
    {
        RequestDict.Remove(request.OpCode);
    }
}

然后在Request腳本里面處理添加和移除Request.

using Common;
using ExitGames.Client.Photon;
using UnityEngine;

public  abstract class Request:MonoBehaviour  {

     public  OperationCode OpCode;
    
     public   abstract void DefaultRequse();//向服務(wù)器發(fā)起請(qǐng)求方法
     public   abstract void OnOperationResponse(OperationResponse operationResponse);//服務(wù)器收到消息響應(yīng)給客戶端的方法

    //當(dāng)這個(gè)組件初始化的時(shí)候添加這個(gè)Request
    public virtual void Start()
    {
        PhotonEngine.Instance.AddRequst(this);
    }
    //當(dāng)這個(gè)組件被銷毀的時(shí)候移除這個(gè)Request
    public void OnDestroy()
    {
        PhotonEngine.Instance.RemoveRequst(this);
    }
}

處理客戶端向服務(wù)器端發(fā)起登陸請(qǐng)求并寫入接受服務(wù)器端響應(yīng)的方法

下面在LoginRequest腳本里的DefaultRequse方法里面開始寫入登陸請(qǐng)求的發(fā)起方法和響應(yīng)的方法了

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

public class LoginRequest : Request
{
    [HideInInspector]
    public  string Username;
    [HideInInspector]
    public   string Password;

    private Loginpanel loginpanel;
  public   override void Start()
    {
        base.Start();
        loginpanel = GetComponent<Loginpanel>();
    }


    //發(fā)起請(qǐng)求
    public override void DefaultRequse()
    {
        Dictionary<byte, object> data = new Dictionary<byte, object>();
        data.Add((byte)ParameterCode.Username,Username);
        data.Add((byte)ParameterCode.Password, Password);
        PhotonEngine.Peer.OpCustom((byte)OpCode,data,true);//把用戶名和密碼傳遞給服務(wù)器
    }
    //得到響應(yīng)
    public override void OnOperationResponse(OperationResponse operationResponse)
    {
        ReturnCode returnCode = (ReturnCode)operationResponse.ReturnCode;
        loginpanel.OnLoginResponse(returnCode);
      
    }
}

然后再Loginpanel腳本里面寫入處理面板UI操作的代碼,順便自行吧點(diǎn)擊登陸按鈕很點(diǎn)擊注冊(cè)按鈕的方法去注冊(cè)上吧韭山。

using UnityEngine;
using UnityEngine.UI;
using Common;

public class Loginpanel : MonoBehaviour {

    public GameObject RegisterPanel;//注冊(cè)面板
    public InputField username;//UI界面輸入的用戶名
    public InputField password;//UI界面輸入的密碼
    private LoginRequest loginRequest;//提示信息

    public Text hintMessage;
    private void Start()
    {

        loginRequest = GetComponent<LoginRequest>();
    }
    //點(diǎn)擊登陸按鈕
    public void OnLoginButton()
    {
        hintMessage.text = "";
        loginRequest.Username = username.text;
        loginRequest.Password = password.text;
        loginRequest.DefaultRequse();
    }
    //點(diǎn)擊注冊(cè)按鈕跳轉(zhuǎn)到注冊(cè)界面
    public void OnRegisterButton()
    {
        gameObject.SetActive(false);
        RegisterPanel.SetActive(true);
    }

    //登陸操作,如果驗(yàn)證成功登陸冷溃,失敗提示用戶或密碼錯(cuò)誤
    public void OnLoginResponse(ReturnCode returnCode)
    {
        if (returnCode == ReturnCode.Success)
        {
            //驗(yàn)證成功掠哥,跳轉(zhuǎn)到下一個(gè)場(chǎng)景
            hintMessage.text = "用戶名和密碼驗(yàn)證成功";
           
        }
        else if (returnCode == ReturnCode.Failed)
        {
     
            hintMessage.text = "用戶名或密碼錯(cuò)誤";
        }
    }
}

這時(shí)候我的客戶端的登陸請(qǐng)求已經(jīng)發(fā)送到了服務(wù)器端并且也寫入了接收服務(wù)器相應(yīng)請(qǐng)求的響應(yīng)的方法了

服務(wù)器端處理接收客戶端的登陸請(qǐng)求并返回響應(yīng)給客戶端

下面我們就要開始處理服務(wù)器端登陸的請(qǐng)求和響應(yīng)客戶端的方法了。
首先我們?cè)诜?wù)器MyGameServer上創(chuàng)建一個(gè)文件夾Hander,后續(xù)會(huì)把所有的請(qǐng)求處理器都放在這個(gè)文件夾里面秃诵,然后再Hander里面創(chuàng)建一個(gè)公共的抽象類BaseHandler來(lái)表示一些基礎(chǔ)的東西续搀,然后再在文件夾Hander下創(chuàng)建LoginHandler類(登陸的Hander)、RegisterHandler類(注冊(cè)的Hander)菠净、DefaultHandler類默認(rèn)的Hander

Paste_Image.png

using Common;
using Photon.SocketServer;

namespace MyGameServer.Handler
{
public abstract class BaseHandler
    {
        
        public OperationCode opCode;
        //處理請(qǐng)求的方法
        public abstract void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer);
      
    }
}

在這之后會(huì)有很多的hander對(duì)象比如請(qǐng)求登陸的hander請(qǐng)求注冊(cè)的hander等等禁舷,這時(shí)候我們需要用一個(gè)字典把這些hander管理起來(lái),在MyGameServer類的初始化方法Setup里面我們用字典把這些hander添加進(jìn)字典管理起來(lái)那就是在MyGameServer改成下面的代碼

using System.Collections.Generic;
using Photon.SocketServer;
using ExitGames.Logging;
using System.IO;
using ExitGames.Logging.Log4Net;
using log4net.Config;
using Common;
using MyGameServer.Handler;

namespace MyGameServer
{
    //所有的Server端 主類都要繼承自applicationbase
    public class MyGameServer : ApplicationBase
    {
        public  static readonly ILogger log = LogManager.GetCurrentClassLogger();//定義一個(gè)Log對(duì)象

        public static MyGameServer Instance { get; private set; }


        //存儲(chǔ)所有的Handler
        public Dictionary<OperationCode, BaseHandler> HandlerDict = new Dictionary<OperationCode, BaseHandler>();


        //當(dāng)一個(gè)客戶端請(qǐng)求連接的時(shí)候彪杉,服務(wù)器端就會(huì)調(diào)用這個(gè)方法
        //我們使用peerbase,表示和一個(gè)客戶端的鏈接,然后photon就會(huì)把這些鏈接管理起來(lái)
        protected override PeerBase CreatePeer(InitRequest initRequest)
        {

            log.Info("一個(gè)客戶端連接進(jìn)來(lái)了!");
            return new ClientPeer(initRequest);
        }
        //初始化(當(dāng)整個(gè)服務(wù)器啟動(dòng)起來(lái)的時(shí)候調(diào)用這個(gè)初始化)
        protected override void Setup()
        {
            Instance = this;

            //日志的初始化(定義配置文件log4net位置)

            //Path.Combine  表示連接目錄和文件名牵咙,可以屏蔽平臺(tái)的差異
            // Photon: ApplicationLogPath 就是配置文件里面路徑定義的屬性
            //this.ApplicationPath 表示可以獲取photon的根目錄,就是Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy這個(gè)目錄
            //這一步是設(shè)置日志輸出的文檔文件的位置派近,這里我們把文檔放在Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\bin_Win64\log里面
            log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(Path.Combine(Path.Combine(this.ApplicationRootPath,"bin_win64")),"log");
            //this.BinaryPath表示可以獲取的部署目錄就是目錄Photon-OnPremise-Server-SDK_v4-0-29-11263\deploy\MyGameServer\bin
            FileInfo configFileInfo = new FileInfo(Path.Combine(this.BinaryPath,"log4net.config"));//告訴log4net日志的配置文件的位置
            //如果這個(gè)配置文件存在
            if (configFileInfo.Exists)
            {
                LogManager.SetLoggerFactory(Log4NetLoggerFactory.Instance);//設(shè)置photon我們使用哪個(gè)日志插件
                XmlConfigurator.ConfigureAndWatch(configFileInfo);//讓log4net這個(gè)插件讀取配置文件
            }



            log.Info("Setup Completed!");//最后利用log對(duì)象就可以輸出了

            InitHandler();

        }

        //用來(lái)初始化Handler
        public void InitHandler()
        {
            LoginHandler loginHandler = new LoginHandler();
            HandlerDict.Add(loginHandler.opCode,loginHandler);
            DefaultHandler defaultHandler = new DefaultHandler();
            HandlerDict.Add(defaultHandler.opCode,defaultHandler);

            RegisterHandler registerHandler = new RegisterHandler();
            HandlerDict.Add(registerHandler.opCode, registerHandler);
        }

        //server端關(guān)閉的時(shí)候
        protected override void TearDown()
        {
            log.Info("關(guān)閉了服務(wù)器");
        }
    }
}

這樣我們所有的hander都添加進(jìn)去管理了起來(lái)。因?yàn)槲颐看稳プ值浍@取值的時(shí)候都要用到TryGetValue的方式去回去比較麻煩所以下面我們給字典加一個(gè)擴(kuò)展方法洁桌,在Common這個(gè)項(xiàng)目里面添加一個(gè)文件夾工具Tools在這里面創(chuàng)建一個(gè)DictTool類渴丸,寫入下面的字典擴(kuò)展方法

using System.Collections.Generic;

namespace Common.Tools
{
   public  class DictTool
    {
       //擴(kuò)展方法
        public static Value GetValue<Key, Value>(Dictionary<Key, Value> dicr, Key key)
        {
            Value value;
           
            bool isSuccess = dicr.TryGetValue(key, out value);
            if (isSuccess)
            {
                return value;
            }
            else
            {
                return default(Value);
            }
        }
    }
}

這樣我們就可以直接獲取值了,然后在管理客戶端的類ClientPeer里面修改處理客戶端請(qǐng)求的方法OnOperationRequest();修改代碼如下

using Photon.SocketServer;
using PhotonHostRuntimeInterfaces;
using MyGameServer.Handler;
using Common.Tools;
using Common;


namespace MyGameServer
{
    //管理跟客戶端的鏈接的
   public  class ClientPeer : Photon.SocketServer.ClientPeer
    {

        public ClientPeer(InitRequest initRequest) : base(initRequest)
        {


        }
        //處理客戶端斷開連接的后續(xù)工作
        protected override void OnDisconnect(DisconnectReason reasonCode, string reasonDetail)
        {
           
        }
        //處理客戶端的請(qǐng)求
        protected override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters)
        {
            //OperationRequest封裝了請(qǐng)求的信息
            //SendParameters 參數(shù),傳遞的數(shù)據(jù)


            //通過客戶端的OperationCode從HandlerDict里面獲取到了需要的Hander
            BaseHandler handler = DictTool.GetValue<OperationCode, BaseHandler>(MyGameServer.Instance.HandlerDict,(OperationCode)operationRequest.OperationCode);
    
           //如果找到了需要的hander就調(diào)用我們hander里面處理請(qǐng)求的方法
            if (handler != null)
            {
                handler.OnOperationRequest(operationRequest, sendParameters, this);

            }
            else//否則我們就使用默認(rèn)的hander
            {
                BaseHandler defaultHandler = DictTool.GetValue<OperationCode, BaseHandler>(MyGameServer.Instance.HandlerDict, OperationCode.Default);
                defaultHandler.OnOperationRequest(operationRequest,sendParameters,this);
            }
       }
    }
}

下面我們就開始處理LoginHandler類里面請(qǐng)求的代碼了

using Photon.SocketServer;
using Common;
using Common.Tools;
using MyGameServer.Manager;


namespace MyGameServer.Handler
{
    //處理登陸請(qǐng)求的類
    class LoginHandler : BaseHandler
    {
        public LoginHandler()
        {
            opCode=OperationCode.Login;//賦值OperationCode為L(zhǎng)ogin,表示處理的是那個(gè)請(qǐng)求
        }
        //登陸請(qǐng)求的處理的代碼
        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer)
        {
            //根據(jù)發(fā)送過來(lái)的請(qǐng)求獲得用戶名和密碼
            string username = DictTool.GetValue<byte, object>(operationRequest.Parameters, (byte)ParameterCode.Username)as string;
            string password= DictTool.GetValue<byte, object>(operationRequest.Parameters, (byte)ParameterCode.Password) as string;
            //連接數(shù)據(jù)庫(kù)進(jìn)行校驗(yàn)
            UserManager manager = new UserManager();
            bool isSuccess = manager.VerifyUser(username, password);
            OperationResponse response = new OperationResponse(operationRequest.OperationCode);
            //如果驗(yàn)證成功另凌,把成功的結(jié)果利用response.ReturnCode返回成功給客戶端
            if (isSuccess)
            {
                response.ReturnCode = (short)Common.ReturnCode.Success;
            }
            else//否則返回失敗給客戶端
            {
                response.ReturnCode = (short)Common.ReturnCode.Failed;
            }
            //把上面的回應(yīng)給客戶端
            peer.SendOperationResponse(response, sendParameters);

        }
    }
}

最后重新生成下MyGameServer,然后在吧Common.dll重新倒入到Unity3D中重啟服務(wù)器
這樣就完成了我們的客戶端發(fā)送請(qǐng)求給服務(wù)器谱轨,服務(wù)器連接數(shù)據(jù)庫(kù)驗(yàn)證用戶信息并把驗(yàn)證結(jié)果返回給客戶端。下面我們來(lái)驗(yàn)證下吠谢,先對(duì)比下數(shù)據(jù)庫(kù)


image.png

然后運(yùn)行Unity客戶端土童,先隨便輸一個(gè),驗(yàn)證失敗工坊,沒毛病献汗。


image.png
下面再來(lái)個(gè)正確的
image.png
當(dāng)然你想改成密碼框直接把下面這個(gè)設(shè)置改成password就可以了
image.png

這樣我們的登陸請(qǐng)求就完成了,接下來(lái)開始處理注冊(cè)的請(qǐng)求王污,其實(shí)原理是一樣的罢吃,接下來(lái)我們來(lái) 看看如何操作。

注冊(cè)請(qǐng)求的發(fā)送

直接在RegisterRequest 腳本里面發(fā)起注冊(cè)請(qǐng)求昭齐,代碼如下

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

public class RegisterRequest : Request
{
    [HideInInspector]
    public string username;
    [HideInInspector]
    public string password;

    private RegistrerPanel registerPanel;
    public override void Start()
    {
        base.Start();
        registerPanel = GetComponent<RegistrerPanel>();
    }
    //發(fā)起請(qǐng)求
    public override void DefaultRequse()
    {
        Dictionary<byte, object> data = new Dictionary<byte, object>();
        data.Add((byte)ParameterCode.Username, username);
        data.Add((byte)ParameterCode.Password, password);
        PhotonEngine.Peer.OpCustom((byte)OpCode, data, true);
    }
    ////得到服務(wù)器的響應(yīng)
    public override void OnOperationResponse(OperationResponse operationResponse)
    {
        ReturnCode returnCode = (ReturnCode)operationResponse.ReturnCode;
        registerPanel.OnRegisterResponse(returnCode);
    }
}

然后在RegistrerPanel腳本里面處理按鈕的點(diǎn)擊事件和驗(yàn)證的方法

using UnityEngine;
using UnityEngine.UI;
using Common;

public class RegistrerPanel : MonoBehaviour {

    public GameObject loginpanel;
    public InputField usernameIF;
    public InputField passwordIF;
    public Text hintMassage;

    private RegisterRequest registerRequest;
    private void Start()
    {
        registerRequest = GetComponent<RegisterRequest>();
    }
    //點(diǎn)擊事件確認(rèn)登陸
    public void OnRegisterButton()
    {
        hintMassage.text = "";
        registerRequest.username = usernameIF.text;
        registerRequest.password = passwordIF.text;
        registerRequest.DefaultRequse();
    }
    //點(diǎn)擊事件返回
    public void OnBackButton()
    {
        loginpanel.SetActive(true);
        gameObject.SetActive(false);

    }
    
    public void OnRegisterResponse(ReturnCode returnCode)
    {
        if (returnCode == ReturnCode.Success)
        {
            hintMassage.text = "注冊(cè)成功尿招,請(qǐng)返回登陸";
              }
        else if (returnCode == ReturnCode.Failed)
        {
            hintMassage.text = "所用的用戶名已被注冊(cè),請(qǐng)更改用戶名";

        }
    }
}

這樣我們客戶端的請(qǐng)求和響應(yīng)就處理完畢了司浪,下面去服務(wù)器端處理請(qǐng)求的接收添加數(shù)據(jù)和對(duì)客戶端做出響應(yīng).

服務(wù)器端處理注冊(cè)請(qǐng)求的接收和響應(yīng)給客戶端

直接在RegisterHandler類里面處理注冊(cè)的請(qǐng)求

using Photon.SocketServer;
using Common;
using Common.Tools;
using MyGameServer.Manager;
using MyGameServer.Model;

namespace MyGameServer.Handler
{
    //處理注冊(cè)請(qǐng)求的類
    class RegisterHandler : BaseHandler
    {
        public RegisterHandler()
        {
            opCode = OperationCode.Register;

        }
        //注冊(cè)請(qǐng)求的處理的代碼
        public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer peer)
        {
            string username = DictTool.GetValue<byte, object>(operationRequest.Parameters, (byte)ParameterCode.Username) as string;
            string password = DictTool.GetValue<byte, object>(operationRequest.Parameters, (byte)ParameterCode.Password) as string;
            UserManager manager = new UserManager();
            User user = manager.GetByUsername(username);//根據(jù)username查詢數(shù)據(jù)
            OperationResponse responser = new OperationResponse(operationRequest.OperationCode);
            //如果沒有查詢到代表這個(gè)用戶沒被注冊(cè)過可用
            if (user == null)
            {
                //添加輸入的用戶和密碼進(jìn)數(shù)據(jù)庫(kù)
                user = new User() { Username = username, Password = password };
                manager.Add(user);
                responser.ReturnCode = (short) ReturnCode.Success;//返回成功

            }
            else//否者這個(gè)用戶被注冊(cè)了
            {
                responser.ReturnCode = (short)ReturnCode.Failed;//返回失敗
            }
            // 把上面的結(jié)果給客戶端
            peer.SendOperationResponse(responser,sendParameters);
        }
    }
}

這樣整個(gè)登陸和注冊(cè)的請(qǐng)求和回應(yīng)都完成了泊业,我們重新生成下重啟服務(wù)器測(cè)試下,啟動(dòng)Unity客戶端,隨便先注冊(cè)個(gè)用戶啊易,然后可以看到注冊(cè)成功了吁伺。


image.png

下面我們打開我們數(shù)據(jù)庫(kù)可以看到我們注冊(cè)的信息傳遞到了數(shù)據(jù)庫(kù)


image.png
然后我們?cè)俳M成相同的用戶名就會(huì)提示已被注冊(cè)
image.png

這樣我們總共的登陸和注冊(cè)就完成了,有具體的細(xì)節(jié)和BUG大家可以自己去調(diào)試

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末租谈,一起剝皮案震驚了整個(gè)濱河市篮奄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌割去,老刑警劉巖窟却,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異呻逆,居然都是意外死亡夸赫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門咖城,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)茬腿,“玉大人呼奢,你說(shuō)我怎么就攤上這事∏衅剑” “怎么了握础?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)悴品。 經(jīng)常有香客問我禀综,道長(zhǎng),這世上最難降的妖魔是什么苔严? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任定枷,我火速辦了婚禮,結(jié)果婚禮上邦蜜,老公的妹妹穿的比我還像新娘依鸥。我一直安慰自己亥至,他們只是感情好悼沈,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著姐扮,像睡著了一般絮供。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上茶敏,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天壤靶,我揣著相機(jī)與錄音,去河邊找鬼惊搏。 笑死贮乳,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的恬惯。 我是一名探鬼主播向拆,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼酪耳!你這毒婦竟也來(lái)了浓恳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤碗暗,失蹤者是張志新(化名)和其女友劉穎颈将,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體言疗,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡晴圾,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了噪奄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片死姚。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡沾凄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出知允,到底是詐尸還是另有隱情撒蟀,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布温鸽,位于F島的核電站保屯,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏涤垫。R本人自食惡果不足惜姑尺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝠猬。 院中可真熱鬧切蟋,春花似錦、人聲如沸榆芦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)匆绣。三九已至驻右,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間崎淳,已是汗流浹背堪夭。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拣凹,地道東北人森爽。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嚣镜,于是被迫代替她去往敵國(guó)和親爬迟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理祈惶,服務(wù)發(fā)現(xiàn)雕旨,斷路器,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,504評(píng)論 25 707
  • API定義規(guī)范 本規(guī)范設(shè)計(jì)基于如下使用場(chǎng)景: 請(qǐng)求頻率不是非常高:如果產(chǎn)品的使用周期內(nèi)請(qǐng)求頻率非常高捧请,建議使用雙通...
    有涯逐無(wú)涯閱讀 2,519評(píng)論 0 6
  • 本文依照 知識(shí)共享許可協(xié)議(署名-非商業(yè)性使用-禁止演繹) 發(fā)布凡涩。 編寫HTTP 服務(wù)器與客戶端 Vert.x讓編...
    半枚荔枝閱讀 3,948評(píng)論 0 5
  • 倘若相遇總是有期限 倘若離別注定要出現(xiàn) 我希望那天能來(lái)得晚一些 讓我來(lái)得及欠身?yè)肀磉叺娜税?來(lái)得及說(shuō)些溫存的話 ...
    鯨鯊閱讀 215評(píng)論 1 9