1. Mirorr 的分层结构
2. 组件生命周期
3. Tranport 支持
提供的不同 Low Level Transport
KCP: reliable UDP
LiteNetLib: UDP
UNET LLAPI: UDP。实测丢包率高
Ignorance: ENET UDP
Libuv: Node.js networking backend
Telepathy: cross platform TCP
Simple Websockets: Websockets
FizzySteam: SteamNetwork
4. LiteNetLib
MaxPacketSize:NetConstants.PossibleMtu
5. 2个端是怎么连到一起的?
测试环境:
一个当主机(Host + Server),另一个连接主机IP
上线游戏环境:
切换到 Linux 环境,打包(Linux上是没有后缀的),然后部署到云端服务器,持续run!
服务器和Mirror包通过 GRP C或者其他方式通信(具体看项目选型,让服务端去烦恼?!)
打包实践,docker集成:Mirror Docker Guide
6. 实现简单多人交互demo
简单的2人交互demo,本地的点击可以同步给其他端,其他端的点击可以正确同步给我
demo:TeddyFrameWork/tree/main/Assets/Standard%20Assets/Mirror/Examples/Example1
直接实现的逻辑,客户端服务端都走一个脚本,有点混乱,所有项目经历了客户端服务端代码分离过程
拆分 Client 和 Server 代码
7. 连上服务端,服务端的数据是怎么同步给本地端的?
看源码的时候,能断点,千万不要硬读源码,很可能掉进深坑
①客户端注册 SpawnMessage 消息
NetworkManagerHUD.OnGUI()
NetworkManagerHUD.StartButtons()
NetworkManager.StartClient()
NetworkClient.Connect()
NetworkClient.RegisterSystemHandlers()
RegisterHandler<SpawnMessage>(OnSpawn);
②连上服务端,服务端遍历所有已准备好的连接,发送 SpawnMessage 给新连上的对象
③客户端收到消息,对服务端下发的对象,进行实例化生成,调用对象的 OnStartClient 方法
8. 断线重连,服务端数据怎么同步给本地端的?
要么在 OnStartClient,Mirror定义好的生命周期函数,对关键字段进行同步
要么用 [SyncVar] 关键字属性,连上同步
要么自己写个协议,在连上服务端进行关键字段同步
9. 收发消息批处理
①MTU
在网络中,最大传输单元(MTU)指通过联网设备可以接收的最大数据包的值。
Transport 决定了 Mirror MTU的大小。
您发送的每条消息都将被批处理,直到帧结束,以最大限度地减少带宽和传输调用。
例如,如果您发送大量 10 字节的消息,那么我们通常可以将其中的约 120 条放入一个MTU大小的批次中,大约 1200 字节。
10. 组件学习
①Network Manager
网络管理单例,有Server/Client/Host运行模式
②Network Behaviour
netId
isLocalPlayer
网络通信组件基类,可以通过 Command/RPC 调用远端函数
③Network Identity
isLocalPlayer
④Network Transform
mirror 版本:V78.4.3
NetworkTransform.cs
伪代码:
LateUpdate
如果是客户端权威
超过发送间隔,就构造快照,发送到服务端,RPC到各个客户端进行快照插值同步
不是客户端权威:
进行快照插值同步
Update
更新快照插值,应用插值结果
TransformSnapshot 实现了简单的快照插值逻辑
启用插值后,会延迟缓冲传入数据,并对值应用额外的平滑处理。导致更平滑的变换同步。减少抖动
NetworkTransform |NetworkTransform |NetworkTransform |NetworkTransform | Unity Multiplayer Networking
⑤Network Animator
动画是怎么同步的?
同步所有 animator.parameters,animator.IsParameterControlledByCurve
伪代码:
FixedUpdate
固定发送频率
检测动画状态是否变化:遍历所有层,animator.IsInTransition(layerId)
检测动画速度是否变化:animator.speed
变化了,就把变化的 状态Hash 和 归一化时间 上报服务器,服务器进行ClientROC
11. AOI(Interest Manager)
①Spatial Hashing Interest Management 组件
把观察者和对象位置四舍五入归一化放在格子里,计算是否相邻
Vector2Int projected = ProjectToGrid(identity.transform.position);
Vector2Int observerProjected = ProjectToGrid(newObserver.identity.transform.position);
// distance needs to be at max one of the 8 neighbors, which is
// 1 for the direct neighbors
// 1.41 for the diagonal neighbors (= sqrt(2))
// => use sqrMagnitude and '2' to avoid computations. same result.
return (projected - observerProjected).sqrMagnitude <= 2;
②Distance Interest Management 组件
Network Proximity Checker
该组件会在配置的更新频率内进行配置的可见距离的检查计算:Vector3.Distance
foreach spawned entity:
foreach connection:
if (Vector3.Distance(spawned, connection) < visRange):
connection.Send(spawned);
12. Authority 权限
identity.AssignClientAuthority
identity.RemoveClientAuthority
13. 作弊与反作弊
客户权威——万恶之源
查找内存位置
大多数作弊需要从游戏内存中读取一些信息。Cheat Engine等工具允许您在游戏内存中搜索特定值。例如,如果您的生命值是 100,那么您搜索“100”可能会在内存中找到 10,000 个值为“100”的位置。
如果我们的游戏使用客户端权限,那么我们实际上可以修改内存中玩家的生命值!如果我们使用服务器权限,那么我们仍然可以在内存中修改它,但更改仅在该客户端可见。服务端不信任客户端的健康值,下次同步新的健康值给客户端时,内存中的值会再次被覆盖。
解决方法1:更难找到内存位置
偏移量
解决方法2:更难访问内存
动态变化的虚假入口点,例如使用UPX 打包器之类的 exe 打包。这些并不难拆开,但它增加了难度。(请注意,UPX 打包的可执行文件通常被标记为病毒。)
通过IsDebuggerPresent检测Cheat Engine/MHS 等调试器。请注意,这很容易变通,因为每个人都已经知道 IsDebuggerPresent。
使用Themida或Enigma Packer 等工具进行虚拟化是防止逆向工程的圣杯。(请注意,虚拟化的可执行文件通常被标记为病毒。您需要一个未标记为病毒的自定义虚拟化引擎。)
todo MLAPI 学习 Netcode For GameObjects
附录
ChatGPT关于如何深入学习Unity的网络开发模块
网络编程基础知识:理解TCP/IP协议栈、Socket编程、网络数据传输等基本概念和原理,这些知识对于理解Unity网络开发模块的工作原理非常重要。
Unity网络开发模块的基本功能:熟悉Unity网络开发模块的基本功能和API,例如UNET、Netcode for GameObjects、Mirror等等。这些模块提供了许多工具和API,用于简化多人联机游戏的开发和管理。
服务器架构和设计:理解多人联机游戏的服务器架构和设计原理,包括客户端和服务器的通信协议、网络同步算法、带宽控制、流量优化等等。这些知识可以帮助开发者设计出更高效、更可靠的多人联机游戏服务器。
性能优化和调试技巧:掌握性能优化和调试技巧,包括网络数据压缩、带宽限制、流量控制、数据同步算法优化、延迟优化等等。这些技巧可以帮助开发者解决网络性能问题,提高游戏体验和稳定性。
都是开头一个标题,内容一大堆的东西。
网络发送的方法有哪些?
TCP、UDP
网络发送中 channel 的作用是什么?
channel 的作用:区分可靠和不可靠频道,方便处理消息收发逻辑区分处理
在经典 UNet 中,QoS Flags 用于确定数据包如何到达远程端。
例如,如果您需要在队列中对数据包进行优先排序,您可以指定一个高优先级标志,然后 Unity LLAPI 将接收并适当处理该标志。
不幸的是,这给传输层带来了很多额外的工作,并且一些 QoS 标志由于依赖太多魔法的错误代码而没有按预期工作。
在 Mirror 中,QoS 标志被替换为“channel ”系统。(虽然默认传输Telepathy根本不使用通道,因为它是基于 TCP 的,但其他传输(例如Ignorance和LiteNetLib)支持它们。)
网络发送中区域剔除的作用是什么?
减小带宽,避免不同战场之间的互相影响。见 InterestManagement
Headless
不用图形界面,不用显示器的服务、软件等
参考
官方文档:Mirror Networking
推荐本站淘宝优惠价购买喜欢的宝贝:
本文链接:https://hqyman.cn/post/9794.html 非本站原创文章欢迎转载,原创文章需保留本站地址!
休息一下~~