使用Unity网络框架快速开发多人联网游戏(1)

Net网络框架基于Socket网络库扩展而成的一款强大的多人在线网络游戏插件(框架),那么下面我就带领大家来学习一个这款网络插件(框架)的开发过程。

 

首先,你的安装unity,  只要unity支持.net4.x版本以上都可以使用此插件框架,那么安装那一步骤我就不一一介绍了。。

第一个步:我们创建一个游戏项目文件

使用Unity网络框架快速开发多人联网游戏(1)_第1张图片

点击确定后,进入unity软件。

然后获取我们的网络框架插件:

使用Unity网络框架快速开发多人联网游戏(1)_第2张图片

上图加群免认证,直接去群文件下载游戏框架插件。

然后进行解压,直接拖到项目中, 下图是插件文件结构

使用Unity网络框架快速开发多人联网游戏(1)_第3张图片

 

我们创建一个脚本,叫做网络管理器:

使用Unity网络框架快速开发多人联网游戏(1)_第4张图片

 

然后双击脚本进入VS2017代码编辑器,然后写上以下代码,  你可以直接复制粘贴

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Net.Client;//网络游戏的客户端命名空间
using Net.Share;//网络服务器的通用命名空间
using System;

//网络游戏管理器
public class NetworkManager : NetClient//继承网络游戏核心客户端基类
{
    // Start is called before the first frame update
    void Start()
    {
        Connect();//1.开始连接服务器
    }

    public void MyConnect()
    {
        Connect("127.0.0.1", 666, result => //2.连接服务器
        {
            //result 为 true 则连接成功, 为假则连接失败 , 此处代码处于多线程, 不允许调用unity的api
        });
    }

    //当连接服务器成功调用
    protected override void OnConnected()
    {
        //此函数处于unity线程, 可以使用unity的api
        Debug.Log("连接成功");
    }

    //当连接失败调用
    protected override void OnConnectFailed()
    {
        //在此函数处理连接失败后的动作
        Debug.Log("连接失败");
    }

    //当客户端与服务器连接中断调用
    protected override void OnConnectLost()
    {
        //处理
        Debug.Log("连接中断");
    }

    //当断开连接调用
    protected override void OnDisconnect()
    {
        //处理
        Debug.Log("断开连接");
    }

    //当连接被断开并且尝试重新连接服务器时调用
    protected override void OnTryToConnect()
    {
        //处理
        Debug.Log("尝试重连");
    }

    //当断线重新连接服务器成功调用
    protected override void OnReconnect()
    {
        //处理
        Debug.Log("断线重连成功");
    }

    //当注册网络类型
    protected override Type[] OnRegNetworkTypes()
    {
        Debug.Log("注册网络类型");
        return new Type[] { typeof(int), typeof(bool), typeof(string), typeof(float) };//注册你的网络类型
    }
}

那么客户端已经有了管理器进行连接服务器的类了,  那么我们现在就要进行编写服务器代码了。

 

首先我们创建一个C#控制台项目:选择解决方案, 然后右键-> 添加->新建项目

使用Unity网络框架快速开发多人联网游戏(1)_第5张图片

选择C#->控制台应用->项目名称, 最后确认就创建好了我们的服务器项目

使用Unity网络框架快速开发多人联网游戏(1)_第6张图片

 

我们在服务器的引用那里右键,然后选择浏览,找到unity的三个dll和GameDesigner.dll文件,然后确认就好了, unity的dll在unity的安装目录下找到, GameDesigner.dll文件就是我们的网络插件dll,在项目里面可以找到

使用Unity网络框架快速开发多人联网游戏(1)_第7张图片

 

新建一个服务器管理器脚本,这个脚本也是最主要的脚本:

使用Unity网络框架快速开发多人联网游戏(1)_第8张图片

使用Unity网络框架快速开发多人联网游戏(1)_第9张图片

 

然后写上代码: 可以直接复制过去粘贴

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Net.Server;//网络游戏服务器命名空间
using Net.Share;//网络游戏通用命名空间

namespace Server
{
    //服务器管理器
    public class ServerManager : NetServer//继承网络游戏的服务器核心基类
    {
        //当服务器开始启动调用
        protected override void OnStarting()
        {
            //处理
            Console.WriteLine("初始化服务器");
        }

        //当服务器启动成功,启动完成调用
        protected override void OnStartupCompleted()
        {
            //处理
            Console.WriteLine("服务器启动成功");
        }

        //当有客户端玩家连接调用
        protected override void OnHasConnect(EndPoint client)//玩家客户端终端
        {
            //处理
            Console.WriteLine("有客户端连接" + client.ToString());
        }

        //当服务器创建主场景调用,  返回主场景键值对,  键为场景名称 值为场景实例
        protected override KeyValuePair OnAddDefaultScene()
        {
            Console.WriteLine("当添加网络主场景");
            return new KeyValuePair("主场景", new NetScene(1000));//返回了一个主场景,并且初始化主场景容纳1000个人同时在主场景内
        }

        //当接收未知的客户端请求调用
        protected override NetPlayer OnUnClientRequest(NetPlayer unClient, byte[] buffer, byte cmd, int index, int count)
        {
            //处理未知客户端数据请求 验证登录 或 注册
            //如果让此函数返回对象实例, 则同意此客户端进入服务器的权限,并添加此客户端到在线玩家集合中, 之后就可以与在线玩家之间的交互,
            //如果返回null,  则服务器不处理此客户端的任何事件, 可以认为服务器不允许此客户端进入游戏,或者登陆失败

            Console.WriteLine("当未知客户端发来的数据请求, 默认直接授权进入多人在线");
            return unClient; //默认服务器直接运行未知客户端进入多人在线集合
        }

        //当接收客户端的自定义byte[]数据请求, 此方法需要使用者自行编写序列化和反序列化进行解析网络数据,  可以使用josn解析 , 此插件使用NetConvert解析
        protected override void OnReceiveBuffer(NetPlayer client, byte cmd, byte[] buffer, int index, int count)
        {
            Console.WriteLine("接收客户端玩家自定义数据请求:" + client.RemotePoint[GetType().GUID].ToString() + " 数据大小: " + count);
            //处理自定义数据,  自定义数据客户端同样有一个自定义的Send方法进行发送数据封包
        }

        //当服务器初始化成功,并收集将要注册的RPC类型时调用, RPC函数是网络可以识别的函数,网络数据会调用那些带有RPC特性的函数, 关键在此方法进行添加
        protected override List OnRegisterRPC()
        {
            Console.WriteLine("注册带有RPC函数的类型对象");
            return base.OnRegisterRPC();
        }

        //当注册网络类型时调用,  服务器的网络类型必须跟客户端的注册网络类型顺序要一致, 因为再解析的过程中用的是索引直接取值, 所以网络类型顺序不能乱
        protected override Type[] OnRegNetworkTypes()
        {
            Console.WriteLine("注册网络类型");
            return new Type[] { typeof(int), typeof(bool), typeof(string), typeof(float) };//注册你的网络类型
        }

        private NetPlayer player;//全局客户端对象, 当RPC函数被调用的过程中,可把此变量当做发送数据方的客户端来看待

        //当即将调用RPC函数时调用,  当即将调用RPC函数时,把player对象给赋值, 这样之后调用的RPC函数内可把此对象当做发送数据方客户端来处理
        protected override void OnInvokeRpc(NetPlayer client)
        {
            Console.WriteLine("开始调用此玩家的RPC函数:" + client.playerID);
            player = client;
        }

        //当客户端异常,服务器移除客户端时调用
        protected override void OnRemoveClient(NetPlayer client)//要移除的客户端对象
        {
            Console.WriteLine("客户端被移除:" + client.playerID);
        }
    }
}
 
  

 

 

然后在Main函数里写上服务器的实例,并启动服务器

使用Unity网络框架快速开发多人联网游戏(1)_第10张图片

 

我们可以看到服务器已经启动成功:

使用Unity网络框架快速开发多人联网游戏(1)_第11张图片

 

然后我们启动客户端进行连接, 能够看到客户端也已经能连接上服务器了

使用Unity网络框架快速开发多人联网游戏(1)_第12张图片

 

这时服务器有响应为有客户端连接, 可以看到客户端连接然后又退出游戏, 那是我连接上然后又关闭了客户端

使用Unity网络框架快速开发多人联网游戏(1)_第13张图片

 

那么现在我们就可以对服务器发送一下数据包了,  我们写个发送字符串函数, 代码如下, 可直接复制粘贴:

 

using UnityEngine;
using System.Collections;
using Net.Client;//网络游戏客户端命名空间
using Net.Share;//网络游戏通用命名空间

//发送消息类型
public class SendMessage : NetBehaviour //此时不能再继承NetClient类型了,//我们接下来所写的网络类型都要继承此NetBehaviour类型, NetBehaviour类型会收集网络RPC函数,如果不继承此类有可能无法调用类内部的RPC函数
{

    private string str;//定义了我们要发送的字符串

    private void OnGUI()
    {
        str = GUI.TextField(new Rect(100,100,200,50), str);//输入我们要发送的字符串

        if (GUI.Button(new Rect(100, 200, 100, 50), "发送"))//如果按下按钮就进行发送数据到服务器
        {
            byte[] buffer = System.Text.Encoding.Unicode.GetBytes(str);//把我们要发送的字符串转出二进制数组的Unicode编码,然后进行发送

            Send(buffer);//发送自定义网络数据
        }
    }
}

 

嗯, 我们有了发送数据类型了,  那么我们还需要在服务器那边处理一下接收自定义类型的数据: 下面代码可以覆盖ServerManager.cs的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Net.Server;//网络游戏服务器命名空间
using Net.Share;//网络游戏通用命名空间

namespace Server
{
    //服务器管理器
    public class ServerManager : NetServer//继承网络游戏的服务器核心基类
    {
        //当服务器开始启动调用
        protected override void OnStarting()
        {
            //处理
            Console.WriteLine("初始化服务器");
        }

        //当服务器启动成功,启动完成调用
        protected override void OnStartupCompleted()
        {
            //处理
            Console.WriteLine("服务器启动成功");
        }

        //当有客户端玩家连接调用
        protected override void OnHasConnect(EndPoint client)//玩家客户端终端
        {
            //处理
            Console.WriteLine("有客户端连接" + client.ToString());
        }

        //当服务器创建主场景调用,  返回主场景键值对,  键为场景名称 值为场景实例
        protected override KeyValuePair OnAddDefaultScene()
        {
            Console.WriteLine("当添加网络主场景");
            return new KeyValuePair("主场景", new NetScene(1000));//返回了一个主场景,并且初始化主场景容纳1000个人同时在主场景内
        }

        //当接收未知的客户端请求调用
        protected override NetPlayer OnUnClientRequest(NetPlayer unClient, byte[] buffer, byte cmd, int index, int count)
        {
            //处理未知客户端数据请求 验证登录 或 注册
            //如果让此函数返回对象实例, 则同意此客户端进入服务器的权限,并添加此客户端到在线玩家集合中, 之后就可以与在线玩家之间的交互,
            //如果返回null,  则服务器不处理此客户端的任何事件, 可以认为服务器不允许此客户端进入游戏,或者登陆失败

            Console.WriteLine("当未知客户端发来的数据请求, 默认直接授权进入多人在线");
            return unClient; //默认服务器直接运行未知客户端进入多人在线集合
        }

        //当接收客户端的自定义byte[]数据请求, 此方法需要使用者自行编写序列化和反序列化进行解析网络数据,  可以使用josn解析 , 此插件使用NetConvert解析
        protected override void OnReceiveBuffer(NetPlayer client, byte cmd, byte[] buffer, int index, int count)
        {
            Console.WriteLine("接收客户端玩家自定义数据请求:" + client.RemotePoint[GetType().GUID].ToString() + " 数据大小: " + count);

            string str = Encoding.Unicode.GetString(buffer, index, count);//接收自定义的数据请求, 数据请求编码要保证一致才能解码成功, 否则会解乱码

            Console.WriteLine("接收的数据内容:" + str);
            //处理自定义数据,  自定义数据客户端同样有一个自定义的Send方法进行发送数据封包
        }

        //当服务器初始化成功,并收集将要注册的RPC类型时调用, RPC函数是网络可以识别的函数,网络数据会调用那些带有RPC特性的函数, 关键在此方法进行添加
        protected override List OnRegisterRPC()
        {
            Console.WriteLine("注册带有RPC函数的类型对象");
            return base.OnRegisterRPC();
        }

        //当注册网络类型时调用,  服务器的网络类型必须跟客户端的注册网络类型顺序要一致, 因为再解析的过程中用的是索引直接取值, 所以网络类型顺序不能乱
        protected override Type[] OnRegNetworkTypes()
        {
            Console.WriteLine("注册网络类型");
            return new Type[] { typeof(int), typeof(bool), typeof(string), typeof(float) };//注册你的网络类型
        }

        private NetPlayer player;//全局客户端对象, 当RPC函数被调用的过程中,可把此变量当做发送数据方的客户端来看待

        //当即将调用RPC函数时调用,  当即将调用RPC函数时,把player对象给赋值, 这样之后调用的RPC函数内可把此对象当做发送数据方客户端来处理
        protected override void OnInvokeRpc(NetPlayer client)
        {
            Console.WriteLine("开始调用此玩家的RPC函数:" + client.playerID);
            player = client;
        }

        //当客户端异常,服务器移除客户端时调用
        protected override void OnRemoveClient(NetPlayer client)//要移除的客户端对象
        {
            Console.WriteLine("客户端被移除:" + client.playerID);
        }
    }
}
 
  

 

我们添加了以下代码来解析客户端发来的Unicode编码数据:

使用Unity网络框架快速开发多人联网游戏(1)_第14张图片

然后在unity的场景层级里面找个物体进行添加了我们的SendMessage组件,运行一下服务器,  再运行客户端进行测试

使用Unity网络框架快速开发多人联网游戏(1)_第15张图片

当我们的客户端写入字符串然后按下发送按钮,  服务器就能看到打印出来一条信息了,  那么现在我们就来实现调用服务器的函数,以下代码为调用服务器函数代码,  可以复制黏贴

using UnityEngine;
using System.Collections;
using Net.Client;//网络游戏客户端命名空间
using Net.Share;//网络游戏通用命名空间

public class CallServerFunc : NetBehaviour//继承网络游戏行为基类
{
    private string parStr;//定义了我们要发送的字符串参数

    private void OnGUI()
    {
        parStr = GUI.TextField(new Rect(300, 100, 200, 50), parStr);//输入我们要发送的字符串参数

        if (GUI.Button(new Rect(300, 200, 100, 50), "调用服务器的Test函数"))//如果按下按钮就进行发送数据到服务器
        {
            Send("Test", parStr);//发送插件内核处理好的RPC函数方法, 发送此数据,服务器必须有Test方法, 而且参数也要匹配
        }
    }
}

然后同样,我们要在服务器添加一个方法来接收客户端发送的函数调用请求

使用Unity网络框架快速开发多人联网游戏(1)_第16张图片

添加了Test方法后完整代码为以下代码,  直接复制黏贴到ServerManager.cs脚本覆盖就行

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Net.Server;//网络游戏服务器命名空间
using Net.Share;//网络游戏通用命名空间

namespace Server
{
    //服务器管理器
    public class ServerManager : NetServer//继承网络游戏的服务器核心基类
    {
        //当服务器开始启动调用
        protected override void OnStarting()
        {
            //处理
            Console.WriteLine("初始化服务器");
        }

        //当服务器启动成功,启动完成调用
        protected override void OnStartupCompleted()
        {
            //处理
            Console.WriteLine("服务器启动成功");
        }

        //当有客户端玩家连接调用
        protected override void OnHasConnect(EndPoint client)//玩家客户端终端
        {
            //处理
            Console.WriteLine("有客户端连接" + client.ToString());
        }

        //当服务器创建主场景调用,  返回主场景键值对,  键为场景名称 值为场景实例
        protected override KeyValuePair OnAddDefaultScene()
        {
            Console.WriteLine("当添加网络主场景");
            return new KeyValuePair("主场景", new NetScene(1000));//返回了一个主场景,并且初始化主场景容纳1000个人同时在主场景内
        }

        //当接收未知的客户端请求调用
        protected override NetPlayer OnUnClientRequest(NetPlayer unClient, byte[] buffer, byte cmd, int index, int count)
        {
            //处理未知客户端数据请求 验证登录 或 注册
            //如果让此函数返回对象实例, 则同意此客户端进入服务器的权限,并添加此客户端到在线玩家集合中, 之后就可以与在线玩家之间的交互,
            //如果返回null,  则服务器不处理此客户端的任何事件, 可以认为服务器不允许此客户端进入游戏,或者登陆失败

            Console.WriteLine("当未知客户端发来的数据请求, 默认直接授权进入多人在线");
            return unClient; //默认服务器直接运行未知客户端进入多人在线集合
        }

        //当接收客户端的自定义byte[]数据请求, 此方法需要使用者自行编写序列化和反序列化进行解析网络数据,  可以使用josn解析 , 此插件使用NetConvert解析
        protected override void OnReceiveBuffer(NetPlayer client, byte cmd, byte[] buffer, int index, int count)
        {
            Console.WriteLine("接收客户端玩家自定义数据请求:" + client.RemotePoint[GetType().GUID].ToString() + " 数据大小: " + count);

            string str = Encoding.Unicode.GetString(buffer, index, count);//接收自定义的数据请求, 数据请求编码要保证一致才能解码成功, 否则会解乱码

            Console.WriteLine("接收的数据内容:" + str);
            //处理自定义数据,  自定义数据客户端同样有一个自定义的Send方法进行发送数据封包
        }

        //当服务器初始化成功,并收集将要注册的RPC类型时调用, RPC函数是网络可以识别的函数,网络数据会调用那些带有RPC特性的函数, 关键在此方法进行添加
        protected override List OnRegisterRPC()
        {
            Console.WriteLine("注册带有RPC函数的类型对象");
            return base.OnRegisterRPC();
        }

        //当注册网络类型时调用,  服务器的网络类型必须跟客户端的注册网络类型顺序要一致, 因为再解析的过程中用的是索引直接取值, 所以网络类型顺序不能乱
        protected override Type[] OnRegNetworkTypes()
        {
            Console.WriteLine("注册网络类型");
            return new Type[] { typeof(int), typeof(bool), typeof(string), typeof(float) };//注册你的网络类型
        }

        private NetPlayer player;//全局客户端对象, 当RPC函数被调用的过程中,可把此变量当做发送数据方的客户端来看待

        //当即将调用RPC函数时调用,  当即将调用RPC函数时,把player对象给赋值, 这样之后调用的RPC函数内可把此对象当做发送数据方客户端来处理
        protected override void OnInvokeRpc(NetPlayer client)
        {
            Console.WriteLine("开始调用此玩家的RPC函数:" + client.playerID);
            player = client;
        }

        //当客户端异常,服务器移除客户端时调用
        protected override void OnRemoveClient(NetPlayer client)//要移除的客户端对象
        {
            Console.WriteLine("客户端被移除:" + client.playerID);
        }

        //远程RPC函数
        [RPCFun]
        private void Test(string info)
        {
            Console.WriteLine($"客户端:{player.RemotePoint[GetType().GUID].ToString()} 调用了Test方法, 参数数值:{info}");
        }
    }
}
 
  

然后将CallServerFunc脚本挂载到游戏物体上,运行服务器,再运行客户端看看结果是什么样子的......

使用Unity网络框架快速开发多人联网游戏(1)_第17张图片

现在我们可以看到已经调用了服务器的Test函数了,  有点神奇吧!!!

 

那么我们现在还有一种方法哦,  就是调用客户端的函数, 这个调用客户端函数可不是本地调用哦,  是调用所有在同一场景内的客户端的指定方法。  那么现在我们就要在Send方法上用到cmd网络命令了,  cmd有几十种网络命令,  也可以自行添加其他你想要的网络命令,  网络命令是byte类型的,  所以最多只能有256个网络命令,  插件内核采用了10个网络命令,  你还可以使用200多个命令,已经够用的了。。。

下面我们来看远程调用所有在同一场景内的客户端的Test函数: 

using UnityEngine;
using System.Collections;
using Net.Client;//网络游戏客户端命名空间
using Net.Share;//网络游戏通用命名空间

//调用其他客户端与此客户端同一场景内的函数
public class CallClientFunc : NetBehaviour//继承网络游戏行为基类
{
    private string parStr;//定义了我们要发送的字符串参数
    private string netInfo;//存储聊天内容

    private void OnGUI()
    {
        parStr = GUI.TextField(new Rect(300, 100, 200, 50), parStr);//输入我们要发送的字符串参数

        if (GUI.Button(new Rect(300, 200, 100, 50), "调用服务器的Test函数"))//如果按下按钮就进行发送数据到服务器
        {
            //NetCmd.SceneCmd : 网络命令, SceneCmd:场景命令, 意义为调用所有在同一场景内的客户端玩家的xxx函数
            //Test :远程调用识别的函数名称
            //parStr : 远程调用的参数
            Send(NetCmd.SceneCmd, "Test", parStr);//发送插件内核处理好的RPC函数方法, 发送此数据,服务器必须有Test方法, 而且参数也要匹配
        }

        GUI.TextField(new Rect(200, 500, 400, 200), netInfo);
    }

    //远程调用此函数
    [RPCFun]
    private void Test(string info)//远程参数
    {
        Debug.Log("xxx客户端调用了Test函数, 传参为:" + info);
        netInfo += info;
    }
}

 

上面代码写上后,我们不需要写服务器对接代码了,  因为那些已经声明过的网络命令已经被框架内核帮我们实现了,使用我们现在直接运行服务器,  然后再运行客户端进行测试,看看效果,  一个客户端是看不出什么效果的,所以我们要编译一个客户端来看看是不是两个unity都能显示同样的消息来:

 

经过刚才调用了一下,结果没有被调用,  经过几次的查找,终于找到了问题,  我们在初始化场景主场景时所给的主场景名为“主场景”,  而我们的客户端没有指定它所在的场景键为哪个场景,  我们需要把客户端的sceneID也改成主场景名称这样两个客户端才能相互得到转发权限

使用Unity网络框架快速开发多人联网游戏(1)_第18张图片

代码完整为以下代码,  直接复制黏贴到ServerManager.cs脚本就可以

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Net.Server;//网络游戏服务器命名空间
using Net.Share;//网络游戏通用命名空间

namespace Server
{
    //服务器管理器
    public class ServerManager : NetServer//继承网络游戏的服务器核心基类
    {
        //当服务器开始启动调用
        protected override void OnStarting()
        {
            //处理
            Console.WriteLine("初始化服务器");
        }

        //当服务器启动成功,启动完成调用
        protected override void OnStartupCompleted()
        {
            //处理
            Console.WriteLine("服务器启动成功");
        }

        //当有客户端玩家连接调用
        protected override void OnHasConnect(EndPoint client)//玩家客户端终端
        {
            //处理
            Console.WriteLine("有客户端连接" + client.ToString());
        }

        //当服务器创建主场景调用,  返回主场景键值对,  键为场景名称 值为场景实例
        protected override KeyValuePair OnAddDefaultScene()
        {
            Console.WriteLine("当添加网络主场景");
            return new KeyValuePair("主场景", new NetScene(1000));//返回了一个主场景,并且初始化主场景容纳1000个人同时在主场景内
        }

        //当接收未知的客户端请求调用
        protected override NetPlayer OnUnClientRequest(NetPlayer unClient, byte[] buffer, byte cmd, int index, int count)
        {
            //处理未知客户端数据请求 验证登录 或 注册
            //如果让此函数返回对象实例, 则同意此客户端进入服务器的权限,并添加此客户端到在线玩家集合中, 之后就可以与在线玩家之间的交互,
            //如果返回null,  则服务器不处理此客户端的任何事件, 可以认为服务器不允许此客户端进入游戏,或者登陆失败

            Console.WriteLine("当未知客户端发来的数据请求, 默认直接授权进入多人在线");
            unClient.sceneID = "主场景";// 默认客户端开始登陆所在的场景为MainScene, 而上面给的主场景键为"主场景",所以客户端默认进入场景也要改sceneID为主场景的ID
            return unClient; //默认服务器直接运行未知客户端进入多人在线集合
        }

        //当接收客户端的自定义byte[]数据请求, 此方法需要使用者自行编写序列化和反序列化进行解析网络数据,  可以使用josn解析 , 此插件使用NetConvert解析
        protected override void OnReceiveBuffer(NetPlayer client, byte cmd, byte[] buffer, int index, int count)
        {
            Console.WriteLine("接收客户端玩家自定义数据请求:" + client.RemotePoint[GetType().GUID].ToString() + " 数据大小: " + count);

            string str = Encoding.Unicode.GetString(buffer, index, count);//接收自定义的数据请求, 数据请求编码要保证一致才能解码成功, 否则会解乱码

            Console.WriteLine("接收的数据内容:" + str);
            //处理自定义数据,  自定义数据客户端同样有一个自定义的Send方法进行发送数据封包
        }

        //当服务器初始化成功,并收集将要注册的RPC类型时调用, RPC函数是网络可以识别的函数,网络数据会调用那些带有RPC特性的函数, 关键在此方法进行添加
        protected override List OnRegisterRPC()
        {
            Console.WriteLine("注册带有RPC函数的类型对象");
            return base.OnRegisterRPC();
        }

        //当注册网络类型时调用,  服务器的网络类型必须跟客户端的注册网络类型顺序要一致, 因为再解析的过程中用的是索引直接取值, 所以网络类型顺序不能乱
        protected override Type[] OnRegNetworkTypes()
        {
            Console.WriteLine("注册网络类型");
            return new Type[] { typeof(int), typeof(bool), typeof(string), typeof(float) };//注册你的网络类型
        }

        private NetPlayer player;//全局客户端对象, 当RPC函数被调用的过程中,可把此变量当做发送数据方的客户端来看待

        //当即将调用RPC函数时调用,  当即将调用RPC函数时,把player对象给赋值, 这样之后调用的RPC函数内可把此对象当做发送数据方客户端来处理
        protected override void OnInvokeRpc(NetPlayer client)
        {
            Console.WriteLine("开始调用此玩家的RPC函数:" + client.playerID);
            player = client;
        }

        //当客户端异常,服务器移除客户端时调用
        protected override void OnRemoveClient(NetPlayer client)//要移除的客户端对象
        {
            Console.WriteLine("客户端被移除:" + client.playerID);
        }

        //远程RPC函数
        [RPCFun]
        private void Test(string info)
        {
            Console.WriteLine($"客户端:{player.RemotePoint[GetType().GUID].ToString()} 调用了Test方法, 参数数值:{info}");
        }
    }
}
 
  

 

然后我们编译unity客户端,运行服务器, 再运行两个客户端进行测试

使用Unity网络框架快速开发多人联网游戏(1)_第19张图片

 

嗯,  已经可以看到调用本地两个客户端的Test函数了。。。有点惊喜吧

 

以上已经可以实现发送自定义数据, 发送RPC网络函数,  调用服务器函数 和 调用同一场景的所有客户端玩家了,  那么我们能不能调用所有服务器的客户端中的函数呢?  答案是可以的,  也就是换了个命令

将 Send(NetCmd.SceneCmd, "Test", parStr);  改成Send(NetCmd.AllCmd, "Test", parStr);就可以调用所有在线玩家的xx函数了

只需要改下命令就执行不同的功能了,  好激动的感觉有木有???

下面我列出几种网络命令和介绍:   代码已经注释的应该详细了,   你如果要自定义网络命令, 可以继承下面的网络命令类型,写上你自己想要的一些网络命令哦。。。

使用Unity网络框架快速开发多人联网游戏(1)_第20张图片

 

到此基础网络框架插件就结束了哦,   如果觉得不错此文章不错, 可以进行收藏转发哦,   如果对你很有帮助也可以给买包烟钱吧

下篇:服务器数据库处理也登陆注册

你可能感兴趣的:(科技,教程,插件,游戏框架,unity)