到目前为止,已经完成了服务端框架的底层功能,那么现在测试的方法仅仅是通过在main函数中写一些测试的一些代码,并没有和Unity真正的结合起来,那么接下来就和Unity结合一下,真正的去做一个完整的登陆注册流程.
既然是登录和注册,那么肯定有登录和注册这2个协议:
(资料图)
我们新建一个LoginMsg的脚本:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;publicclassMsgRegister:MsgBase{publicMsgRegister(){protoName="MsgRegister";}//客户端publicstringid="";publicstringpw="";//服务器返回-0成功-1失败publicintresult=0;}publicclassMsgLogin:MsgBase{publicMsgLogin(){protoName="MsgLogin";}//客户端publicstringid="";publicstringpw="";//服务器返回-0成功-1失败publicintresult=0;}publicclassMsgKick:MsgBase{publicMsgKick(){protoName="MsgKick";}//下线原因publicintreason=0;}
接下来要对协议进行处理:
我们起个名字:LoginMsgHandle,注意虽然这个脚本的名字叫这个,但是他也是算一个EventHandler的一个组合类.不要被Unity开发中创建脚本的形式给迷惑了.
登录注册以及下线,下线是用来在2个客户端同时登录一个账号的时候需要:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;publicpartialclassMsgHandler{//注册协议处理publicstaticvoidMsgRegister(ClientStatec,MsgBasemsgBase){MsgRegistermsg=(MsgRegister)msgBase;//执行数据库语法尝试注册if(DbManager.Register(msg.id,msg.pw)){DbManager.CreatPlayer(msg.id);msg.result=0;}else{msg.result=1;}//将结果返回给客户端NetManager.Send(c,msg);}//登录协议处理publicstaticvoidMsgLogin(ClientStatec,MsgBasemsgBase){MsgLoginmsg=(MsgLogin)msgBase;//密码校验if(!DbManager.CheckPassword(msg.id,msg.pw)){msg.result=1;NetManager.Send(c,msgBase);return;}//如果已经在线,并在此客户端上又尝试登录if(c.player!=null){msg.result=1;NetManager.Send(c,msgBase);return;}//如果其他客户端登录,踢下线if(PlayerManager.isOnline(msg.id)){//发送踢下线协议Playerother=PlayerManager.GetPlayer(msg.id);MsgKickmsgKick=newMsgKick();msgKick.reason=0;other.Send(msgKick);//协议发送//断开连接NetManager.Close(other.state);}//获取玩家数据PlayerDataplayerData=DbManager.GetPlayerData(msg.id);if(playerData==null){msg.result=1;NetManager.Send(c,msg);return;}//构建playerPlayerplayer=newPlayer(c);player.id=msg.id;player.data=playerData;PlayerManager.AddPlayer(msg.id,player);c.player=player;//返回协议msg.result=0;player.Send(msg);}publicstaticvoidOnDisconnect(ClientStatec){Console.WriteLine("Close");//Player下线if(c.player!=null){//保存数据DbManager.UpdatePlayerData(c.player.id,c.player.data);//移除PlayerManager.RemovePlayer(c.player.id);}}}
到目前为止服务端的功能基本写完,接下来要到Unity中,,写客户端的功能,首先要搭建一个场景,场景布置如下:
2个输入框以及登录注册按钮.
新建一个test脚本文件:
流程同样是先连接服务器然后监听一些回调方法.首先是连接服务器以及数据处理的一些方法,这些方法都是之前章节中所写过的,所以这次我们直接复制过来:
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingSystem.Linq;usingTMPro;publicclasstest:MonoBehaviour{privatevoidStart(){NetManager.Connect("127.0.0.1",8888);}privatevoidUpdate(){NetManager.Update();}}
还有就是把登录注册的协议也要复制过来:
服务器开始的同时运行此脚本,发现连接没有任何问题,接下来就是要做的就是把我们的登录注册协议写进去:
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingSystem.Linq;usingTMPro;publicclasstest:MonoBehaviour{publicTMP_InputFieldidInput;publicTMP_InputFieldpwInput;privatevoidStart(){NetManager.Connect("127.0.0.1",8888);NetManager.AddMsgListener("MsgMove",OnMsgMove);NetManager.AddEventListener(NetManager.NetEvent.ConnectSucc,OnConnectSucc);NetManager.AddEventListener(NetManager.NetEvent.ConnectFail,OnConnectFail);NetManager.AddEventListener(NetManager.NetEvent.Close,OnConnectClose);}voidOnConnectSucc(stringerr){Debug.Log("连接成功...");}voidOnConnectFail(stringerr){Debug.Log("连接失败...");}voidOnConnectClose(stringerr){Debug.Log("连接关闭...");}//发送注册协议publicvoidOnRegister(){MsgRegistermsg=newMsgRegister();msg.id=idInput.text;msg.pw=pwInput.text;NetManager.Send(msg);Debug.Log(msg.protoName);Debug.Log(msg.id);Debug.Log(msg.pw);}//收到注册协议publicvoidOnMsgRegister(MsgBasemsgBase){MsgRegister msg = msgBase as MsgRegister;if(msg.result==0){Debug.Log("注册成功");}else{Debug.Log("注册失败!");}}//发送登录协议publicvoidOnLoginClick(){MsgLoginmsg=newMsgLogin();msg.id=idInput.text;msg.pw=pwInput.text;NetManager.Send(msg);}//收到登录协议publicvoidOnMsgLogin(MsgBasemsgBase){MsgLogin msg = msgBase as MsgLogin;if(msg.result==1){Debug.Log("登录成功");}else{Debug.Log("登录失败");}}//踢下线voidOnMsgKick(MsgBasemsgBase){Debug.Log("被踢下线");}privatevoidUpdate(){NetManager.Update();}
然后把输入框赋值一下:
我们先尝试运行一下,先输入一个错误的用户名和密码按登录键:
发现服务器已经调用成功,接下来我们用正确的账户名和密码登录一下:
那么再试试注册的方法:
如果是写一个已经存在的账号:
相反,写一个没有注册过的账号:
那么再看看数据库中的内容:
发现了一个bug,客户端没有打印出状态信息,经检查,是协议名字写错了:
修改一下:
usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;usingSystem;usingSystem.Linq;usingTMPro;publicclasstest:MonoBehaviour{publicTMP_InputFieldidInput;publicTMP_InputFieldpwInput;privatevoidStart(){NetManager.Connect("127.0.0.1",8888);NetManager.AddMsgListener("MsgMove",OnMsgMove);NetManager.AddMsgListener("MsgLogin",OnMsgLogin);NetManager.AddMsgListener("MsgRegister",OnMsgRegister);NetManager.AddEventListener(NetManager.NetEvent.ConnectSucc,OnConnectSucc);NetManager.AddEventListener(NetManager.NetEvent.ConnectFail,OnConnectFail);NetManager.AddEventListener(NetManager.NetEvent.Close,OnConnectClose);}publicvoidSend(){MsgMovemsgMove=newMsgMove{x=10,y=2,z=-110};NetManager.Send(msgMove);}publicvoidOnMsgMove(MsgBasemsgBase){MsgMovemsg=msgBaseasMsgMove;Debug.Log(msg.protoName);Debug.Log(msg.x);Debug.Log(msg.y);Debug.Log(msg.z);}voidOnConnectSucc(stringerr){Debug.Log("连接成功...");}voidOnConnectFail(stringerr){Debug.Log("连接失败...");}voidOnConnectClose(stringerr){Debug.Log("连接关闭...");}//发送注册协议publicvoidOnRegister(){MsgRegistermsg=newMsgRegister();msg.id=idInput.text;msg.pw=pwInput.text;NetManager.Send(msg);}//收到注册协议publicvoidOnMsgRegister(MsgBasemsgBase){MsgRegistermsg=msgBaseasMsgRegister;if(msg.result==0){Debug.Log("注册成功");}else{Debug.Log("注册失败!");}}//发送登录协议publicvoidOnLoginClick(){MsgLoginmsg=newMsgLogin();msg.id=idInput.text;msg.pw=pwInput.text;NetManager.Send(msg);}//收到登录协议publicvoidOnMsgLogin(MsgBasemsgBase){MsgLoginmsg=msgBaseasMsgLogin;Debug.Log(msg.result);if(msg.result==1){Debug.Log("登录成功");}else{Debug.Log("登录失败");}}//踢下线voidOnMsgKick(MsgBasemsgBase){Debug.Log("被踢下线");}privatevoidUpdate(){NetManager.Update();if(Input.GetKeyDown(KeyCode.A)){Send();}}
结果如下:
enjoy it !!!
本案例的客户端与服务器源码下载方法:公众号回复 服务器开发即可.
X 关闭