Unity Mirror 从入门到入神(一)

Mirror从入门到成神

文章目录

  • Mirror从入门到成神
    • 简介
    • NetworkClient
      • RegisterPrefab
      • Connect (string address)
      • Disconnect ()
      • active
      • activeHost
    • NetworkServer
      • Spawn

简介

Mirror是一个unity网络同步框架,基于MonoBehaviour生命周期的回调的基础上进行数值的同步,将通讯方式和协议剥离,顶层业务只需关注写入读取流,具体传输协议由底层不同协议实现模块完成,使用Mirror编写网络联网游戏,需要掌握分布式编程,要习惯异步的思维,一个方法执行之后无法立刻拿到结果,可以利用协程来检查或者依托特定对象生命周期,也可以使用服务器回调的形式来做,先来看看unity原本的生命周期,关键是easy to use,国外倒是挺火的,国内没啥声响,我们团队在鉴于自己的实际情况,看重的就是一套代码管理,无需额外专职后端开发(项目小)

Unity的MonoBehavior生命周期事件包括Awake、Start、FixedUpdate、Update、LateUpdate、OnEnable、OnDisable和OnDestroy。
Mirror的NetworkManager,NetworkBehavior 图片来源于官网
在这里插入图片描述

在这里插入图片描述

在Mirror中相对本身的生命周期会多几个,可以在Mirror的官网查看详情NetworkBehaviour Callbacks

为了方便理解这里我们首先抽离一个概念,客户端(Client)和服务器(Server),在mirror中他们都是同一个项目的编译产物,在源头上是共生的,内部通过一些特定的标志来判定对应的逻辑代码是否应该执行,比如扣减用户血量,这种安全性要求较高的逻辑内容理应放置到服务器中执行,也有叫前端,后端的,我们选择mirror的原因是因为可以同项目管理,不需要额外的项目和开发人员来支撑服务端,大部分的游戏逻辑都可以公用,比如游戏功能道具啊,Server发布的时候非特殊要求的情况下使用Dedicated Server的方式进行发布,如果形象的形容是Headless无头,如果接触过爬虫的就会知道 无头浏览器的概念。及没有渲染能力的游戏客户端。

启动游戏服务端的时候有几个模式,分别是Host,Server Only,Client Only。主机模式,仅启动服务端,仅启动客户端,说白了我们把游戏逻辑写道一起,如果要完成的进行游戏,就必须同时具备Server,Client 都在线的情况。Host 启动后运行服务器代码,也运行客户端代码。Server Only仅运行服务端代码,Client仅运行客户端代码,下图为Host模式的结构性说明

在这里插入图片描述

RemoteClient表示通过网络通讯协议接入的其他客户端,Local Client在Mirror中做了特殊处理,并不会走网络协议,而是直接将数据写入一个本地队列,另外还有一些执行差异,后面会提到。这里总结下能运行完整游戏的方式

  1. 以HOST模式启动
  2. 连接其他HOST模型启动的程序
  3. 连接其他Server模式启动的程序

下图展示的是数据流的流动方向,对应Spawn出来的单位,服务器和所有客户端都会存在一个实例,由Mirror控制并将对应的数据分发给这些实例对象,其中通过NetworkIdentity的NetId来区分作为全网的唯一标识(全网指的是本局游戏类,连进Server的Client组成的网络)

在这里插入图片描述

下图展示的是Mirror 的层级构成,这个图上包含的类就是Mirror的核心类,这个图最好能背下来,有利于后续的Mirror学习, 对于只是利用Mirror完成联网游戏的改造和编写只需要知道NetworkClient向下的内容,现在来介绍下这些核心组件
在这里插入图片描述

NetworkClient

负责客户端上的和服务端的网络通讯,通常对于开发人员是不需要关注的,除非有定制化的需求

完整的api文档 这里介绍下几个可能会用到的

RegisterPrefab

该函数用于注册预制体,所有需要利用Mirror进行动态生成单位,都需要完成预制体的注册,有两种方式一种是在NetworkManager中RegisteredSpawnablePrefabs列表中添加对应的预制体,要添加成功需要该预制体存在NetworkIdentify组件,否则无法添加,也可以点击Inspector界面的PopulateSpawnablePrefabs,该功能可以自动扫描当前项目中所有添加了NetworkIdentify的预制体,能够自动将预制体添加到列表中,这里很容易犯一个小错误,如果预制体的名字一致,但是错误提示没有注册,可以检查是否是名字一样实则不同的预制体,方式二就是点在运行期间通过

RegisterPrefab (GameObject prefab, Guid newAssetId, SpawnHandlerDelegate spawnHandler, UnSpawnDelegate unspawnHandler)

该方法进行注册,需要注意的是注册的预制体需要在各个端都存在,否则注册之后会出问题。后面的SpawnHander UnSpawnDelegate 可以拦截系统的Spawn 和UnSpawn事件,找一个很容易理解的例子 Instantiate (实例化)Desotry (销毁)。客户端在收到UnSpawn默认的行为是Desotry掉,如果想要池化联网对象,就需要依靠上面的SpawnHander方法,另外该方法一个AssetId只能调用一次,不可以重复调用,如果需要替换请使用其他方法,该方法还有其他的重载,想要细致了解的化可以查看官方文档

Connect (string address)

链接远程服务器,address地址通过是一个ip,具体的端口信息在Transport.active中持有,通过这种方式可以修改端口,也就说明了Transport.active是单例的

    if (Transport.active is PortTransport portTransport){// use TryParse in case someone tries to enter non-numeric charactersportTransport.Port = ushort.Parse(port);}

根据源码具体看看这部分是怎么做的

     public static void Connect(string address){Initialize(false);AddTransportHandlers();//connectState = ConnectState.Connecting;Transport.active.ClientConnect(address);connection = new NetworkConnectionToServer();}

Transport是一个接口interface,不同的传续协议都会实现,这里我们抽一个KcpTransport看一下

在这里插入图片描述

//KcpTransport.cs#ClientConnectpublic override void ClientConnect(string address)
{client.Connect(address, Port);
}
//KcpConnect.cs#ClientConnectpublic void Connect(string address, ushort port){if (connected){Log.Warning("[KCP] Client: already connected!");return;}// resolve host name before creating peer.// fixes: https://github.com/MirrorNetworking/Mirror/issues/3361if (!Common.ResolveHostname(address, out IPAddress[] addresses)){// pass error to user callback. no need to log it manually.OnError(ErrorCode.DnsResolve, $"Failed to resolve host: {address}");OnDisconnectedCallback();return;}// create fresh peer for each new session// client doesn't need secure cookie.Reset(config);Log.Info($"[KCP] Client: connect to {address}:{port}");// create socketremoteEndPoint = new IPEndPoint(addresses[0], port);socket = new Socket(remoteEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);active = true;// recv & send are called from main thread.// need to ensure this never blocks.// even a 1ms block per connection would stop us from scaling.socket.Blocking = false;// configure buffer sizesCommon.ConfigureSocketBuffers(socket, config.RecvBufferSize, config.SendBufferSize);// bind to endpoint so we can use send/recv instead of sendto/recvfrom.socket.Connect(remoteEndPoint);// immediately send a hello message to the server.// server will call OnMessage and add the new connection.// note that this still has cookie=0 until we receive the server's hello.SendHello();}

当然也可以调用Connect的其他重载

// 	Connect client to a NetworkServer by address. More...
static void 	Connect (string address)
//Connect client to a NetworkServer by Uri. More...
static void 	Connect (Uri uri)
//字如其名
static void 	ConnectHost ()

Disconnect ()

断开连接

active

在不想将MonoBehavior 改成NetworkBehavior时非常有用,使用NetworkBehavior可以在对象内使用isServer,IsClient来判断是否是服务器,还是客户端,但是这会增加带宽的负担,及时一个变量都不需要同步,所以该静态变量在全局判断时非常有用

activeHost

联网游戏存在单机模式,我们用Mirror变成完成之后使用Host模式即可将游戏变为单机模式,这里有一个技巧即可以使用 NetworkServer.dontListen = true;来不启动端口监听。因为Host模式调用远程ClientRpc时,时不会执行的,还有Spawn事件也不会执行,所以需要依靠这些判断该字段来附加执行属于Host的业务逻辑

NetworkServer

接下来看看NetworkServer,听名字就知道这个东西适合服务器相关的,这个普通开发人员也不需要关注,但是任然需要对他有所了解,如果是在不想管,那就记一个方法就行Spawn

Spawn

// 	Spawn the given game object on all clients which are ready. More...
static void 	Spawn (GameObject obj, NetworkConnection ownerConnection=null)
// 	Spawns an object and also assigns Client Authority to the specified client. More... 
static void 	Spawn (GameObject obj, GameObject ownerPlayer)
// 	Spawns an object and also assigns Client Authority to the specified client. More... 
static void 	Spawn (GameObject obj, Guid assetId, NetworkConnection ownerConnection=null)

一般使用他的流程是,在服务端上执行,首先实例化某个Prefab,Instantiate创建好GameObject obj = Instantiate(Prefab),在设置好属性位置啥的(除了transform以外其他都需要是同步属性,否则需要在客户端自行设置)然后调用NetworkServer.Spawn(obj)这样就可以把obj同步给所有端了。第二个 第三个参数是为了标识当前这个obj是属于那个客户端的,该逻辑会在Client2Server的传输模式非常有用,客户端会自行判断如果自己是owner就会同步数据给服务器,否则会直接跳过数据传输部分,服务器也会校验该对象是否允许客户端进行修改。服务器具有权威性,从游戏的数据安全角度考虑,Mirror设计了自己的鉴权逻辑,后面会说到。

Client2Server是数据传输的方向,该方向仅仅对 OwnerClient与Server之间有影响,其他关系都是客户端接收服务器的同步

ClientRpc 是一种注解,可以明确告知Mirror这是一个存在与客户端上的远程方法,Mirror会自动根据方法名调用所有客户端 对应对象的obj执行

Mirror从入门到入神(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/707291.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本三剑客-awk

一、awk的介绍 1.1awk的简介 AWK 是一种处理文本文件的语言,是一个强大的文本分析工具 可以在无交互的模式下实现复杂的文本操作 相较于sed常作用于一整个行的处理,awk则比较倾向于一行当中分成数个字段来处理,因为awk相当适合小型的文本…

SQL已知2商品的总价,求商品的数量

已知商品1和2价格,求商品1的数量(商品2的数量自动计算),使得商品总价小于并最接近目标总价的值; 解决: 使用MySQL数据库: -- 创建表 CREATE TABLE products (price_1 INT,price_2 INT,target_p…

回顾程序员18年自己取得的一些成绩有想卖ERP源码的冲动

好久没来csdn发文章,记录自己程序员生涯的心得了,回顾自己2006年湘大信息计算科学专业毕业,当年和班里其他两个同学被招录进富士康,做为新干班签了3年半的合同,在那呆了2年,感觉富士康毕竟是个制造业&#…

HackTheBox-Machines--Bank

文章目录 0x01 信息收集0x02 文件上传漏洞利用0x03 权限提升方法一:SUID提权方法二:配置不当提权 Bank 测试过程 0x01 信息收集 1.端口扫描 发现 ssh(22)、DNS(53)、HTTP(80) 端口 nmap -sC -sV 10.129.29.200访问 80 端口,页面为Apache2 U…

翻译《The Old New Thing》- Stupid debugger tricks: Calling functions and methods

Stupid debugger tricks: Calling functions and methods - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20070427-00/?p27083 Raymond Chen 2007年04月27日 一个比较笨的调试技巧:调用函数和方法 在过去,如果你想在…

大模型时代,交换机技术演变、性能分析、衡量指标

OSI协议及在高性能计算中向RDMA的过渡 协议是为计算机网络内的数据交换而建立的一组规则、标准或协议。在法律层面,OSI七层协议被视为国际标准。该协议于20世纪80年代引入,旨在通过其七层网络模型标准化计算机间通信,以满足开放网络的要求。…

Lazyboy品牌发布会“球幕气膜”

Lazyboy品牌发布会“球幕气膜”为品牌活动提供了一个独特、现代化、环保的展示空间。这座球幕气膜不仅为发布会提供了一个视觉震撼的场地,也为与会嘉宾带来了全新的体验。作为轻空间(江苏)膜科技有限公司(以下简称“轻空间”&…

C++ 数据结构算法 学习笔记(25) - 图及其企业级应用

C 数据结构算法 学习笔记(25) - 图及其企业级应用 图的故事导入 故事情节 Jack 自从买车后,交通出行方便了,心自然就野了!身边的各种朋友自然就多了起来! 有一天晚上,一个年轻漂亮的女同事生日,Jack 受邀…

可用在vue自动导入的插件unplugin-auto-import

在大多数vue3开发中,基本所有页面都会引用vue3 componsition api,如下代码 想这种vue3 架构中自带的api,如果在全局配置一下的话,就可以减少一部分代码量,只是在代码编译的时候,会添加相应的引用&#xff…

ArcGIS arcpy代码工具——关于标识码的那些事(查找最大标识码、唯一性检查、重排序、空值赋值)

系列文章目录 ArcGIS arcpy代码工具——批量对MXD文件的页面布局设置修改 ArcGIS arcpy代码工具——数据驱动工具批量导出MXD文档并同步导出图片 ArcGIS arcpy代码工具——将要素属性表字段及要素截图插入word模板 ArcGIS arcpy代码工具——定制属性表字段输出表格 ArcGIS arc…

复制即用!纯htmlcss写的炫酷input输入框

一般我们写css样式都要用样式库,但是嫌麻烦,如果能找到现成的内容复制上去就很香了,下文是笔者觉得好看的纯html&css写的样式,可以直接复制到Vue等内,十分方便。 input组件 1) 下面这个很推荐&#…

C++的数据结构(九): 笛卡尔树

笛卡尔树(Cartesian Tree)是一种特殊的二叉树,其每个节点的键值(key)满足二叉搜索树的性质,即左子树上所有节点的键值小于根节点的键值,右子树上所有节点的键值大于根节点的键值。与此同时&…