[从零开始的Unity网络同步] 2.服务端与客户端之间通信
在上一篇文章中,介绍了如何在Unity中启动服务端和客户端以及客户端连接服务端的方法,接下来,将通过自定义消息类型,实现服务端与客户端之间的通信.
1.自定义消息类型(CustomMsgTypes)
其实在上一篇文章中,已经知道如何注册消息回调了,就是使用RegisterHandler
方法,这个方法的第一个参数short
类型的变量,第二个参数是NetworkMessageDelegate
类型的委托,如果消息注册方法,我们就可以自定义MsgType,来处理游戏内的逻辑.代码如下
public class CustomMsgTypes
{
public const short InGameMsg = 1003;
}
这个消息的定义,需要注意UnityEngine.Networking下内置的MsgType已经占用了一些数值,避免与Unity自带的MsgType重复.然后把CustomMsgTypes注册到网络组件的消息回调:
// 在服务端注册消息
public override void RegisterMsgHandles()
{
// 注册自定义消息类型
NetworkServer.RegisterHandler(CustomMsgTypes.InGameMsg, OnRecvCustomMsg);
}
// 回调方法
protected void OnRecvCustomMsg(NetworkMessage netMsg)
{
Debug.LogWarning("OnRecvCustomMsg");
}
2.定义自定义消息
已经定义了消息类型,接下来,要定义这个消息类型对应的消息内容,在UnityEngine.Networking组件下,定义的Message要继承自MessageBase,基类有两个方法 Deserialize
和 Serialize
需要重写,也就是消息的序列化和反序列化.代码如下:
public class CustomMessage : MessageBase
{
public int messageId;
public string content;
public Vector3 vector;
public byte[] bytes;
public override void Serialize(NetworkWriter writer)
{
writer.Write(messageId);
writer.Write(content);
writer.Write(vector);
writer.WriteBytesAndSize(bytes, bytes.Length);
}
public override void Deserialize(NetworkReader reader)
{
messageId = reader.ReadInt32();
content = reader.ReadString();
vector = reader.ReadVector3();
ushort count = reader.ReadUInt16();
bytes = reader.ReadBytes(count);
}
}
需要注意的是 Serialize
方法是msg在发送的时候自动调用的,而Deserialize
方法需要在收到消息包的时候主动调用:
protected void OnRecvCustomMsg(NetworkMessage netMsg)
{
CustomMessage msg = new CustomMessage();
msg.Deserialize(netMsg.reader);
Debug.LogWarning("OnRecvCustomMsg");
Debug.LogWarning("messageId:"+msg.messageId);
Debug.LogWarning("content:"+msg.content);
Debug.LogWarning("vector:" + msg.vector);
Debug.LogWarning("bytesLength:" + msg.bytes.Length);
}
3. 发送自定义消息
好了,现在自定义消息的类型与消息内容都有了,现在我们只需要在客户端往消息里填充数据,执行NetworkConnection.Send
方法就可以发送消息了.
// 发送消息
public void Send()
{
CustomMessage message = new CustomMessage();
message.messageId = Time.frameCount;
message.content = "I am Client!";
message.vector = new Vector3(0,5,0);
message.bytes = new byte[100];
connection.Send(CustomMsgTypes.InGameMsg, message); // 使用Unity的NetworkConnection来发送消息
}
在服务端,就可以接受到消息,通过Deserialize
可以获取到消息内容.
4.小结
通过上述的例子,实现 服务端注册自定义消息 => 客户端构造消息并发送 => 服务端接收解析获取数据 ,如果想要把服务端的消息发到客户端,也是这个流程.
下一篇文章将通过目前网上别的游戏的同步架构来探讨<游戏中网络同步的解决方案>,敬请期待.