[从零开始的Unity网络同步] 2.服务端与客户端之间通信

发表于2018-11-15
评论5 5.3k浏览

上一篇文章中,介绍了如何在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,基类有两个方法 DeserializeSerialize 需要重写,也就是消息的序列化和反序列化.代码如下:

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.小结

通过上述的例子,实现 服务端注册自定义消息 => 客户端构造消息并发送 => 服务端接收解析获取数据 ,如果想要把服务端的消息发到客户端,也是这个流程.
下一篇文章将通过目前网上别的游戏的同步架构来探讨<游戏中网络同步的解决方案>,敬请期待.

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引