Photon Server 实现注册与登录(三) --- 前端UI设计和发起请求
一、打开之前的测试项目。先将服务端代码编译一下,在 bin/Debug/目录下会发现有一个Common.dill。我们相应导入到前端使用。直接拖拽到相应地方
UI相应布局属于前端操作,这里就不做介绍了。详细查看视频:https://www.bilibili.com/video/av35109390/?p=70
二、代码处理:跟后端一样,前端发起请求的地方也会随着项目变大而变多,所以也得单独区分出每个请求独自管理。
Request.cs 请求基类
LoginRequest.cs 登录请求逻辑
RegiesterRequest.cs 注册请求连接
LoginPanel.cs 登录面挂载脚本
ReginsterPanel.cs 注册脚本挂载脚
三、调整PhotonManager.cs 管理类
(1)、添加字典,管理所以请求
private Dictionary<OperationCode,Request> ResquesDict = new Dictionary<OperationCode, Request>();
(2)、分配peer
public static PhotonPeer Peer { get { return peer; } }
(3)、添加两个函数,管理请求
public void AddRequest(Request rest) { ResquesDict.Add(rest.OpCode,rest); } public void RemoveRequest(Request rest) { ResquesDict.Remove(rest.OpCode); }
(4)、修改OnOperationResponse() 函数,实现接收服务端返回数据的分发
/// <summary> /// 客户端请求后,服务端响应,返回数据 /// </summary> /// <param name="operationResponse"></param> public void OnOperationResponse(OperationResponse operationResponse) { //服务端返回的code OperationCode opCode = (OperationCode)operationResponse.OperationCode; Request request = null; //根据code查找相应请求 bool tmp = ResquesDict.TryGetValue(opCode, out request); if (tmp) { //如果存在,分发给相应OnOperationResponse去处理自己的接收数据逻辑 request.OnOperationResponse(operationResponse); } else { Debug.Log("没找到响应处理对象"); } }
(5)、完整代码
using System; using System.Collections; using System.Collections.Generic; using System.Reflection.Emit; using Common; using UnityEngine; using ExitGames.Client.Photon; public class PhotonManager : MonoBehaviour,IPhotonPeerListener { //单例模式,保证只有一个链接服务器 public static PhotonManager Instance; private static PhotonPeer peer; private bool connected; private Dictionary<OperationCode,Request> ResquesDict = new Dictionary<OperationCode, Request>(); public static PhotonPeer Peer { get { return peer; } } private void Awake() { if (Instance == null) { Instance = this; DontDestroyOnLoad(this.gameObject); }else if (Instance != this) { Destroy(this.gameObject); return; } } // Start is called before the first frame update void Start() { Debug.Log("111------开始连接----"); peer = new PhotonPeer(this, ConnectionProtocol.Udp); peer.Connect("127.0.0.1:5055","MyGame1"); connected = false; } // Update is called once per frame void Update() { Debug.Log("update------" + connected); peer.Service(); } private void OnDestroy() { if (peer != null && peer.PeerState == PeerStateValue.Connected) { peer.Disconnect(); } } public void DebugReturn(DebugLevel level, string message) { } /// <summary> /// 客户端请求后,服务端响应,返回数据 /// </summary> /// <param name="operationResponse"></param> public void OnOperationResponse(OperationResponse operationResponse) { //服务端返回的code OperationCode opCode = (OperationCode)operationResponse.OperationCode; Request request = null; //根据code查找相应请求 bool tmp = ResquesDict.TryGetValue(opCode, out request); if (tmp) { //如果存在,分发给相应OnOperationResponse去处理自己的接收数据逻辑 request.OnOperationResponse(operationResponse); } else { Debug.Log("没找到响应处理对象"); } } /// <summary> /// 连接状态发生改变时 /// </summary> /// <param name="statusCode"></param> public void OnStatusChanged(StatusCode statusCode) { Debug.Log("serStatus-----" + statusCode.ToString()); switch (statusCode) { case StatusCode.Connect: connected = true; break; default: connected = false; break; } } /// <summary> /// 服务端直接给客户端数据时,不需要向服务器请求 /// </summary> /// <param name="eventData"></param> public void OnEvent(EventData eventData) { switch (eventData.Code) { case 1: break; case 2: break; default: break; } } public void AddRequest(Request rest) { ResquesDict.Add(rest.OpCode,rest); } public void RemoveRequest(Request rest) { ResquesDict.Remove(rest.OpCode); } }
四、请求类
(1)、Request.cs 基类
using System; using Common; using ExitGames.Client.Photon; using UnityEngine; public abstract class Request: MonoBehaviour { //定义请求code public OperationCode OpCode; public abstract void DefaultRequest(); //发送请求 public abstract void OnOperationResponse(OperationResponse operationResponse); //接收返回的数据 public virtual void Start() { //从管理类中添加该请求 PhotonManager.Instance.AddRequest(this); } public void OnDestroy() { //从管理类中移除该请求 PhotonManager.Instance.RemoveRequest(this); } }
(2)、登陆类 LoginRequest.cs
using System.Collections.Generic; using Common; using ExitGames.Client.Photon; using UnityEngine; public class LoginRequest : Request { //通过代码赋值,所有在UI界面上隐藏掉 [HideInInspector] public string UserName; [HideInInspector] public string Password; //获取UI面板 private LoginPanel loginPanel; public override void Start() { //调用基类Start,将登陆请求添加到管理类中 base.Start(); loginPanel = GetComponent<LoginPanel>(); } public override void DefaultRequest() { //登录请求发起 Dictionary<byte,object> data = new Dictionary<byte, object>(); data.Add((byte) ParameterCode.UserName,UserName); data.Add((byte) ParameterCode.Password,Password); //通过Peer发送请求给服务端 PhotonManager.Peer.OpCustom((byte)OpCode,data,true); } public override void OnOperationResponse(OperationResponse operationResponse) { //接收服务端的返回响应,将返回code给面板,由面板来处理接下来的逻辑(是提示错误还是跳转场景) ReturnCode returnCode = (ReturnCode) operationResponse.ReturnCode; loginPanel.OnLiginResponse(returnCode); } }
(3)、登陆面板脚本 LoginPannel.cs
using System; using System.Collections; using System.Collections.Generic; using Common; using UnityEngine; using UnityEngine.UI; public class LoginPanel : MonoBehaviour { //以下public参数通过UI拖拽进行赋值 #region Tags //注册面板,用于点击注册时显示该面板 public GameObject registerPanel; //控件 public InputField username; public InputField password; public Text hintmessage; //登陆请求类 private LoginRequest loginRequest; #endregion private void Start() { //从面板中获取请求类(面板脚本和请求类都挂载到请求面板UI中) loginRequest = GetComponent<LoginRequest>(); } public void OnLoginButton() { //点击登陆按钮时,发送请求 hintmessage.text = ""; loginRequest.UserName = username.text; loginRequest.Password = password.text; //调用请求类中的发起请求 loginRequest.DefaultRequest(); } public void OnRegisterButton() { //点击注册时,隐藏登陆UI,显示注册UI gameObject.SetActive(false); registerPanel.SetActive(true); } public void OnLiginResponse(ReturnCode returnCode) { //服务端响应返回数据时,请求类会将返回信息传递到该函数 Debug.Log("-----返回code" + returnCode); if (returnCode == ReturnCode.Success) { //登录成功,调整下一个场景 Debug.Log("--登陆成功----"); } else { hintmessage.text = "用户名或密码错误"; } } }
注册类和注册面板跟登陆相同逻辑
(4)、注册类 ReginesterRequest.cs
using System.Collections; using System.Collections.Generic; using Common; using ExitGames.Client.Photon; using UnityEngine; public class RegiesterRequet : Request { [HideInInspector] public string username; [HideInInspector] public string password; private ReginsterPanel reginsterPanel; public override void Start() { base.Start(); reginsterPanel = GetComponent<ReginsterPanel>(); } public override void DefaultRequest() { //登录请求发起 Dictionary<byte,object> data = new Dictionary<byte, object>(); data.Add((byte) ParameterCode.UserName,username); data.Add((byte) ParameterCode.Password,password); PhotonManager.Peer.OpCustom((byte)OpCode,data,true); } public override void OnOperationResponse(OperationResponse operationResponse) { ReturnCode returnCode = (ReturnCode) operationResponse.ReturnCode; reginsterPanel.OnReigsterResponse(returnCode); } }
(5)、注册面板 ReginsterPanel.cs
using System; using System.Collections; using System.Collections.Generic; using Common; using UnityEngine; using UnityEngine.UI; public class ReginsterPanel : MonoBehaviour { public GameObject loginPanel; public InputField username; public InputField password; public Text hintmessage; private RegiesterRequet regiesterRequet; private void Start() { regiesterRequet = GetComponent<RegiesterRequet>(); } public void OnRegisterButton() { hintmessage.text = ""; regiesterRequet.username = username.text; regiesterRequet.password = password.text; regiesterRequet.DefaultRequest(); } public void OnBackBtn() { loginPanel.SetActive(true); gameObject.SetActive(false); } public void OnReigsterResponse(ReturnCode returnCode) { if (returnCode == ReturnCode.Success) { hintmessage.text = "注册成功,请返回登录"; } else { hintmessage.text = "用户名重复,请重新修改用户名"; } } }
前端UI和请求、响应逻辑基本完成。接下来进行服务端响应。
查看视频:https://www.bilibili.com/video/av35109390/?p=70