前言
完成项目的注册登录系统,了解与服务器进行交互以及数据校验,为了方面这边就用注释的方式来阐述。
一、UI准备
注册登录的UI按个人喜好而定,基本上的输入就那几块,我这边就简单演示,主要是代码注释的形式,更加的人性化
登录
注册
二、客户端逻辑脚本编写
为了减少耦合性,这边login为一个脚本,register为一个脚本,并挂载到响应的UI组件上
UserService 处理UI层传递参数,进行逻辑处理
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using Network;
using UnityEngine;
using SkillBridge.Message;
namespace Services
{
class UserService : Singleton<UserService>, IDisposable
{
public UnityEngine.Events.UnityAction<Result, string> OnRegister; //创建注册事件
public UnityEngine.Events.UnityAction<Result, string> OnLogin; //创建登录事件
NetMessage pendingMessage = null; //存储因链接断开而未能发送的信息
bool connected = false; //判断链接是否连通
public UserService() //构造函数
{
NetClient.Instance.OnConnect += OnGameServerConnect; //添加链接事件
NetClient.Instance.OnDisconnect += OnGameServerDisconnect; //添加断开事件
MessageDistributer.Instance.Subscribe<UserRegisterResponse>(this.OnUserRegister); //注册消息分发,执行注册方法
MessageDistributer.Instance.Subscribe<UserLoginResponse>(this.OnUserLogin); // //登录消息分发,执行注册方法
}
public void Dispose()
{
MessageDistributer.Instance.Unsubscribe<UserRegisterResponse>(this.OnUserRegister);
MessageDistributer.Instance.Unsubscribe<UserLoginResponse>(this.OnUserLogin);
NetClient.Instance.OnConnect -= OnGameServerConnect;
NetClient.Instance.OnDisconnect -= OnGameServerDisconnect;
}
public void Init()
{
}
public void ConnectToServer()
{
Debug.Log("ConnectToServer() Start ");
//NetClient.Instance.CryptKey = this.SessionId;
NetClient.Instance.Init("127.0.0.1", 8000);
NetClient.Instance.Connect();
}
void OnGameServerConnect(int result, string reason) //链接方法
{
Log.InfoFormat("LoadingMesager::OnGameServerConnect :{0} reason:{1}", result, reason);
if (NetClient.Instance.Connected) //判断链接是否
{
this.connected = true; //至为True;
if(this.pendingMessage!=null) //判断上次链接是否剩下信息没有发送
{
NetClient.Instance.SendMessage(this.pendingMessage); //把没有发送的重新发送
this.pendingMessage = null;//清空
}
}
else
{
if (!this.DisconnectNotify(result, reason))
{
MessageBox.Show(string.Format("网络错误,无法连接到服务器!\n RESULT:{0} ERROR:{1}", result, reason), "错误", MessageBoxType.Error);
}
}
}
public void OnGameServerDisconnect(int result, string reason) //断开方法
{
this.DisconnectNotify(result, reason);
return;
}
bool DisconnectNotify(int result,string reason)
{
if (this.pendingMessage != null)
{
if (this.OnRegister != null)
{
this.OnRegister(Result.Failed, string.Format("服务器断开!\n RESULT:{0} ERROR:{1}", result, reason));
}
return true;
}
return false;
}
public void SendRegister(string user, string psw) //注册信息发送
{
Debug.LogFormat("UserRegisterRequest::user :{0} psw:{1}", user, psw);
NetMessage message = new NetMessage(); //创建网络消息用来跟服务端通信
message.Request = new NetMessageRequest();//实例化消息请求
message.Request.userRegister = new UserRegisterRequest(); //实例化注册请求
message.Request.userRegister.User = user; //给注册请求参数赋值
message.Request.userRegister.Passward = psw;
if (this.connected && NetClient.Instance.Connected) //判断链接是否链接上
{ //链接上就发送之前没有发送的消息
this.pendingMessage = null;
NetClient.Instance.SendMessage(message);
}
else //没有链接上就把未能发送的消息存储,并执行重连
{
this.pendingMessage = message;
this.ConnectToServer();
}
}
void OnUserRegister(object sender, UserRegisterResponse response) //注册响应事件
{
Debug.LogFormat("OnUserRegister:{0} [{1}]", response.Result, response.Errormsg);
if (this.OnRegister != null)
{
this.OnRegister(response.Result, response.Errormsg);
}
}
void OnUserLogin(object sender,UserLoginResponse response)//登录响应事件
{
Debug.LogFormat("OnUserLogin:{0} [{1}]", response.Result, response.Errormsg);
if (this.OnLogin != null)
{
this.OnLogin(response.Result, response.Errormsg);
}
}
public void SendLogin(string user,string psw) //发送登录信息,和发送注册差不多
{
Debug.LogFormat("OnUserLogin::user:{0} psw:{1}", user, psw);
NetMessage message = new NetMessage();
message.Request = new NetMessageRequest();
message.Request.userLogin = new UserLoginRequest();
message.Request.userLogin.User = user;
message.Request.userLogin.Passward = psw;
if (this.connected && NetClient.Instance.Connected)
{
this.pendingMessage = null;
NetClient.Instance.SendMessage(message);
}
else
{
this.pendingMessage = message;
this.ConnectToServer();
}
}
}
1.登录脚本
UILogin.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Services;
using SkillBridge.Message;
using TMPro;
public class UILogin : MonoBehaviour {
public TMP_InputField username; //这边使用TMP的原因是因为比原生的GUI性能强
public TMP_InputField password;
// Use this for initialization
void Start () {
UserService.Instance.OnLogin = OnLogin; //开始先执行一次登录消息的创建,保证链接是通畅的
}
// Update is called once per frame
void Update () {
}
public void OnClickLogin() //登录按钮按下时
{
if (string.IsNullOrEmpty(this.username.text)) //判断当前输入框是否为空
{
MessageBox.Show("请输入账号");
return;
}
if (string.IsNullOrEmpty(this.password.text))
{
MessageBox.Show("请输入密码");
return;
}
// Enter Game
UserService.Instance.SendLogin(this.username.text,this.password.text); //传递参数,让Service处理请求
}
void OnLogin(Result result, string message)
{
//接收从服务器传来的Result类型和消息
if (result == Result.Success)
{
//登录成功,进入角色选择
MessageBox.Show("登录成功,准备角色选择" + message,"提示", MessageBoxType.Information);
SceneManager.Instance.LoadScene("CharSelect");
}
else
MessageBox.Show(message, "错误", MessageBoxType.Error);
}
}
2.注册脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using Services;
using SkillBridge.Message;
using TMPro;
public class UIRegister : MonoBehaviour {
public TMP_InputField username;
public TMP_InputField password;
public TMP_InputField passwordConfirm;
public Button buttonRegister;
public GameObject uiLogin;
// Use this for initialization
void Start () {
UserService.Instance.OnRegister = OnRegister; //和Login一致 先链接
}
// Update is called once per frame
void Update () {
Debug.Log(username.text);
Debug.Log(username);
}
public void OnClickRegister()
{
if (string.IsNullOrEmpty(this.username.text)) //数据校验进行判空
{
MessageBox.Show("请输入账号");
return;
}
if (string.IsNullOrEmpty(this.password.text))
{
MessageBox.Show("请输入密码");
return;
}
if (string.IsNullOrEmpty(this.passwordConfirm.text))
{
MessageBox.Show("请输入确认密码");
return;
}
if (this.password.text != this.passwordConfirm.text)
{
MessageBox.Show("两次输入的密码不一致");
return;
}
UserService.Instance.SendRegister(this.username.text,this.password.text); //发送注册消息
}
void OnRegister(Result result, string message)
{
if (result == Result.Success) //处理服务器返回的信息
{
//登录成功,进入角色选择
MessageBox.Show("注册成功,请登录", "提示", MessageBoxType.Information).OnYes = null;
this.gameObject.SetActive(false);
uiLogin.SetActive(true);
}
else
MessageBox.Show(message, "错误", MessageBoxType.Error);
}
}
二、服务端处理
客户端有UserService 服务端自然也要有
1.Uservice.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Common;
using Network;
using SkillBridge.Message;
//using GameServer.Entities;
using GameServer.Managers;
namespace GameServer.Services
{
class UserService : Singleton<UserService>
{
public UserService() //构造函数
{
MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<UserRegisterRequest>(this.OnRegister); //消息订阅,只要有注册消息来就执行相应的方法
MessageDistributer<NetConnection<NetSession>>.Instance.Subscribe<UserLoginRequest>(this.OnLogin); //消息订阅,只要有登录消息来就执行相应的方法
}
public void Init()
{
}
void OnLogin(NetConnection<NetSession> sender, UserLoginRequest request) //处理登录消息
{
Log.InfoFormat("用户登录响应:User:{0} Pass:{1}", request.User, request.Passward);
NetMessage message = new NetMessage(); //创建网络响应消息
message.Response = new NetMessageResponse();
message.Response.userLogin = new UserLoginResponse();
TUser user = DBService.Instance.Entities.Users.Where(u => u.Username == request.User).FirstOrDefault(); //这边用DBService简写了SQL语句,进行统一封装,效果其实还是那个效果
//正常数据校验
if(user.Username.Equals(request.User)&& user.Password.Equals(request.Passward)){
message.Response.userLogin.Result = Result.Success; //校验成功就将结果设为成功
message.Response.userLogin.Errormsg = "None";
}
else
{
message.Response.userLogin.Result = Result.Failed;//校验失败就将结果设为成功
message.Response.userLogin.Errormsg = "账户名或者密码错误,请检查";//返回错误信息
}
byte[] data = PackageHandler.PackMessage(message); //将消息进行封包
sender.SendData(data, 0, data.Length); //发送响应,回复客户端
}
//和登录的基本构造差不多
void OnRegister(NetConnection<NetSession> sender, UserRegisterRequest request)
{
Log.InfoFormat("UserRegisterRequest: User:{0} Pass:{1}", request.User, request.Passward);
NetMessage message = new NetMessage();
message.Response = new NetMessageResponse();
message.Response.userRegister = new UserRegisterResponse();
TUser user = DBService.Instance.Entities.Users.Where(u => u.Username == request.User).FirstOrDefault();
if (user != null)
{
message.Response.userRegister.Result = Result.Failed;
message.Response.userRegister.Errormsg = "用户已存在.";
}
else
{
TPlayer player = DBService.Instance.Entities.Players.Add(new TPlayer());
DBService.Instance.Entities.Users.Add(new TUser() { Username = request.User, Password = request.Passward, Player = player });
DBService.Instance.Entities.SaveChanges();
message.Response.userRegister.Result = Result.Success;
message.Response.userRegister.Errormsg = "None";
}
byte[] data = PackageHandler.PackMessage(message);
sender.SendData(data, 0, data.Length);
}
}
}
总结
基本流程大概这样,ET框架基本上把底层封装好了,我们只需要调用相应的方法即可,简简单单,没有脑袋。