到目前为止,已经完成了服务端框架的底层功能,那么现在测试的方法仅仅是通过在main函数中写一些测试的一些代码,并没有和Unity真正的结合起来,那么接下来就和Unity结合一下,真正的去做一个完整的登陆注册流程.
既然是登录和注册,那么肯定有登录和注册这2个协议:
我们新建一个LoginMsg的脚本:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class MsgRegister : MsgBase
{
public MsgRegister()
{
protoName = "MsgRegister";
}
//客户端
public string id = "";
public string pw = "";
//服务器返回 -0成功 -1失败
public int result = 0;
}
public class MsgLogin : MsgBase
{
public MsgLogin()
{
protoName = "MsgLogin";
}
//客户端
public string id = "";
public string pw = "";
//服务器返回 -0成功 -1失败
public int result = 0;
}
public class MsgKick : MsgBase
{
public MsgKick()
{
protoName = "MsgKick";
}
//下线原因
public int reason = 0;
}
接下来要对协议进行处理:
我们起个名字:LoginMsgHandle,注意虽然这个脚本的名字叫这个,但是他也是算一个EventHandler的一个组合类.不要被Unity开发中创建脚本的形式给迷惑了.
登录注册以及下线,下线是用来在2个客户端同时登录一个账号的时候需要:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public partial class MsgHandler
{
//注册协议处理
public static void MsgRegister(ClientState c, MsgBase msgBase)
{
MsgRegister msg = (MsgRegister)msgBase;
//执行数据库语法尝试注册
if (DbManager.Register(msg.id, msg.pw))
{
DbManager.CreatPlayer(msg.id);
msg.result = 0;
}
else
{
msg.result = 1;
}
//将结果返回给客户端
NetManager.Send(c, msg);
}
//登录协议处理
public static void MsgLogin(ClientState c, MsgBase msgBase)
{
MsgLogin msg = (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))
{
//发送踢下线协议
Player other = PlayerManager.GetPlayer(msg.id);
MsgKick msgKick = new MsgKick();
msgKick.reason = 0;
other.Send(msgKick);//协议发送
//断开连接
NetManager.Close(other.state);
}
//获取玩家数据
PlayerData playerData = DbManager.GetPlayerData(msg.id);
if (playerData == null)
{
msg.result = 1;
NetManager.Send(c, msg);
return;
}
//构建player
Player player = new Player(c);
player.id = msg.id;
player.data = playerData;
PlayerManager.AddPlayer(msg.id, player);
c.player = player;
//返回协议
msg.result = 0;
player.Send(msg);
}
public static void OnDisconnect(ClientState c)
{
Console.WriteLine("Close");
//Player 下线
if (c.player != null)
{
//保存数据
DbManager.UpdatePlayerData(c.player.id, c.player.data);
//移除
PlayerManager.RemovePlayer(c.player.id);
}
}
}
到目前为止服务端的功能基本写完,接下来要到Unity中,,写客户端的功能,首先要搭建一个场景,场景布置如下:
2个输入框以及登录注册按钮.
新建一个test脚本文件:
流程同样是先连接服务器然后监听一些回调方法.首先是连接服务器以及数据处理的一些方法,这些方法都是之前章节中所写过的,所以这次我们直接复制过来:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using TMPro;
public class test : MonoBehaviour
{
private void Start()
{
NetManager.Connect("127.0.0.1", 8888);
}
private void Update()
{
NetManager.Update();
}
}
还有就是把登录注册的协议也要复制过来:
服务器开始的同时运行此脚本,发现连接没有任何问题,接下来就是要做的就是把我们的登录注册协议写进去:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using TMPro;
public class test : MonoBehaviour
{
public TMP_InputField idInput;
public TMP_InputField pwInput;
private void Start()
{
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);
}
void OnConnectSucc(string err)
{
Debug.Log("连接成功...");
}
void OnConnectFail(string err)
{
Debug.Log("连接失败...");
}
void OnConnectClose(string err)
{
Debug.Log("连接关闭...");
}
//发送注册协议
public void OnRegister()
{
MsgRegister msg = new MsgRegister();
msg.id = idInput.text;
msg.pw = pwInput.text;
NetManager.Send(msg);
Debug.Log(msg.protoName);
Debug.Log(msg.id);
Debug.Log(msg.pw);
}
//收到注册协议
public void OnMsgRegister(MsgBase msgBase)
{
MsgRegister msg = msgBase as MsgRegister; if (msg.result == 0)
{
Debug.Log("注册成功");
}
else
{
Debug.Log("注册失败!");
}
}
//发送登录协议
public void OnLoginClick()
{
MsgLogin msg = new MsgLogin();
msg.id = idInput.text;
msg.pw = pwInput.text;
NetManager.Send(msg);
}
//收到登录协议
public void OnMsgLogin(MsgBase msgBase)
{
MsgLogin msg = msgBase as MsgLogin; if (msg.result == 1)
{
Debug.Log("登录成功");
}
else
{
Debug.Log("登录失败");
}
}
//踢下线
void OnMsgKick(MsgBase msgBase)
{
Debug.Log("被踢下线");
}
private void Update()
{
NetManager.Update();
}
然后把输入框赋值一下:
我们先尝试运行一下,先输入一个错误的用户名和密码按登录键:
发现服务器已经调用成功,接下来我们用正确的账户名和密码登录一下:
那么再试试注册的方法:
如果是写一个已经存在的账号:
相反,写一个没有注册过的账号:
那么再看看数据库中的内容:
发现了一个bug,客户端没有打印出状态信息,经检查,是协议名字写错了:
修改一下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Linq;
using TMPro;
public class test : MonoBehaviour
{
public TMP_InputField idInput;
public TMP_InputField pwInput;
private void Start()
{
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);
}
public void Send()
{
MsgMove msgMove = new MsgMove
{
x = 10,
y = 2,
z = -110
};
NetManager.Send(msgMove);
}
public void OnMsgMove(MsgBase msgBase)
{
MsgMove msg = msgBase as MsgMove;
Debug.Log(msg.protoName);
Debug.Log(msg.x);
Debug.Log(msg.y);
Debug.Log(msg.z);
}
void OnConnectSucc(string err)
{
Debug.Log("连接成功...");
}
void OnConnectFail(string err)
{
Debug.Log("连接失败...");
}
void OnConnectClose(string err)
{
Debug.Log("连接关闭...");
}
//发送注册协议
public void OnRegister()
{
MsgRegister msg = new MsgRegister();
msg.id = idInput.text;
msg.pw = pwInput.text;
NetManager.Send(msg);
}
//收到注册协议
public void OnMsgRegister(MsgBase msgBase)
{
MsgRegister msg = msgBase as MsgRegister;
if (msg.result == 0)
{
Debug.Log("注册成功");
}
else
{
Debug.Log("注册失败!");
}
}
//发送登录协议
public void OnLoginClick()
{
MsgLogin msg = new MsgLogin();
msg.id = idInput.text;
msg.pw = pwInput.text;
NetManager.Send(msg);
}
//收到登录协议
public void OnMsgLogin(MsgBase msgBase)
{
MsgLogin msg = msgBase as MsgLogin;
Debug.Log(msg.result);
if (msg.result == 1)
{
Debug.Log("登录成功");
}
else
{
Debug.Log("登录失败");
}
}
//踢下线
void OnMsgKick(MsgBase msgBase)
{
Debug.Log("被踢下线");
}
private void Update()
{
NetManager.Update();
if (Input.GetKeyDown(KeyCode.A))
{
Send();
}
}
结果如下:
enjoy it !!!
本案例的客户端与服务器源码下载方法:公众号回复 服务器开发 即可.