欢迎来到飞鸟慕鱼博客,开始您的技术之旅!
当前位置: 首页知识笔记正文

Games104现代游戏引擎笔记 网络游戏架构基础

墨初 知识笔记 93阅读



客户端和服务端很多时候系统 OS 不一样
1.常见的有Linux作为服务器收发处理数据客户端是安卓 IOSWindows
2.Big Ending 和 Small Ending, 高位在前还是低位在前
3.数据打包之后需要对齐4个Byte为单位否则就会有很多空间浪费
4.解密和加密
让程序员像正常写业务代码作为一个库存在然后传入参数。之后如何变成Message如何打包如何序列化网络如何路由到服务器服务器如何接受处理消息如何返回等等这些都交给RPC来完成
案例
免去后台的处理过程专注业务逻辑

IDL Interface Definition Language 界面定义语言

IDL 会定义各种参数类似schema的定义
RPC Stubs RPC 存根:
当一个客户端或服务器起来之后彼此会告诉对方自己上线然后注册一大堆的RPC用来个函数调用。
每次call RPC时可以在RPC的存根里查询如果没有对应RPC系统会报错但不影响其他业务逻辑的运行。

真实RPC路径发出RPC请求后首先进行压缩加密然后网络传输服务器接收后进行解密解压缩

Network Topology 网络拓扑


现在多人游戏用的比较少很多时候是点对点时使用主要是switch这种局域网上使用p2p连接
p2p一般不会考虑作弊没有什么限制
相比P2P会选择一个玩家作为一个主机然后传输早期网吧很多局域网游戏是这种类型。
现在一些沙盒类游戏还有steam上的很多游戏是这种方式
不需要开发商维护一个服务器玩家自己可以作为服务器
专用服务器用于更复杂的大型MMO电竞对战
会在服务端维持一个一致的世界所有的客户端获得相对公平且稳定的连接

当跨越大洋的时候物理延迟就是也需要考虑的。尤其是对于全球发行的游戏
所以各个区域一般都设置Protol然后protol通过专有网络会链接到服务器上从而不会使用公网的转跳大大降低延迟
网络游戏加速器也是基于这个原理

Game Synchronization Intro 游戏同步


单人运行单人输入


操作和显示是有延迟的所以需要同步两个世界
1.快照同步 2.帧同步 3.状态同步

Snapshot Synchronization

客户端只负责把输入发给服务器
服务器进行整个游戏世界的模拟
把整个游戏世界的状态生成一个快照每个物体的血量位置速度。。。
将快照发送给客户端
客户端展示快照的数据信息渲染绘制
保证了整个世界状态的一致性客户端只是一个渲染绘制的表现。


服务器会希望快照的计算不要占用过多的带宽帧率会较低10-20左右客户端为了更丝滑的效果帧率会更高。
客户端会在两个服务器快照之间进行插值


快照的数据量较大且往往两个快照间多数物体没有变化因此快照一般传递的是变化量减少传输数据的大小
优点
1.代码非常的简洁干净
2.绝对一致无法作弊
缺点
1.客户端的算力被浪费掉
2.生成快照的数据量很大所需的上传带宽非常大

Lockstep Synchronization


可以理解为军队行走整齐划一某种程度上的高度性
也可以理解为是有回合制的是有顺序的类比与下棋
所有的信息一致性的同步的传递给目标目标一致的处理

最简单的思想
所有客户端的操作统一的发给服务器服务器再同一的分发给客户端客户端做一致的模拟。
服务器一般做信息的汇总同步及转发的处理


第一步初始化游戏内的初始状态王者荣耀的加载条必须要做到完全的一致因为同步的是操作如果初始条件有一丝偏差最终结果可能误差非常大。
还需要同步时钟

每一帧都接受所有的客户端输入确认收到所有输入后统一的发给所有人所有人然后同时开始模拟

优点简洁明了
缺点延迟非常明显所有人的延迟等于延迟最高客户端的延迟


公网帧同步的优化
引入了Bucket每隔一个Bucket(例如100ms)的时间内 未收到客户端的操作则丢弃这个客户端的操作

网络差者获利与网络优者获利。权衡一致性和实时性

帧同步需要整个游戏逻辑具有确定性(Deterministic)
一样的输入经过各种复杂的迭代运算后保持一致结果很难
浮点数
随机数
数据容器计算的算法
数学库
物理的模拟
逻辑执行顺序
帧同步上述一定都要保证一致

浮点数存储要符合IEEE754的标准可以严格意义上保证浮点数一致性
但是不同平台的实现是不一样的

很多数学运算中需要用到三角函数根号等需要用查表法所有的数字必须要是锁死的不能各自算各自的
使用Fixed-point number 定点数的方法来计算使用固定长的数字来处理数学运算从而保证高度的一致性

整个游戏保持一致确定性几乎是不可能的要把最核心的业务逻辑确定一致性。比如角色的移动位置血量一些游戏的状态。但是渲染这种不确定不会有太大影响



同步随机数种子且随机算法必须一致

游戏的确定性是帧同步的基础如果无法保证一致性则帧同步不能成立

跟踪和调试
错误是会不断累积的需要不停地把游戏的状态保存下来使用checksum的方法。
checksum把现在所有的变量存在一起算出一个md5编码存出去把游戏里所有的函数的call和parameter编程一个hash值存在那。可能每5-10帧存下快照包括input也保存快照

滞后和延迟
把服务器传过来的帧cache几帧当服务器出现延迟本地逻辑帧依旧能从cache获取
例如网络视频播放是分成很多块每次下载好几块作为cachebuffer
逻辑帧和渲染帧分离
服务器差不多10帧期间插入很多渲染帧。

当网络出现延迟或者各种问题时渲染帧画面不会因此出现各种各样的抖动。


断线重连
客户端不仅仅只接收input每隔一定帧数会有特定key frame把当前所有游戏的状态做一个snapshot并存在本地的内存或磁盘保证游戏即使崩溃snapshot的快照还在。
每次重连从上一次快照的帧数开始演算到当前的帧数。避免从头开始演算

如果发生了重连情况那么可以放弃渲染帧只跑逻辑帧以更快速度的逻辑帧一定能追上现在游戏的进度

服务器再一些特定的keyFrame保存一个快照

当有些玩家断线时间过长服务器可以给个更新的快照帮助客户端设置游戏的状态

另一个应用是观战模式
观战实际上与断线重连的底层技术一模一样。服务器把前面关键帧的信息发送给客户端再把参与玩家的input发送给客户端。注意观战发送的数据是有主动延迟防止作弊
回放同理

帧同步防作弊
多人情况下投票机制每隔一段时间让所有客户端把游戏里状态的checksum校验码发给服务器然后进行对比有不一样的直接踢掉
双人对战的情况下服务器会有个checksum。有来校验。通常大部分双人游戏都是采用p2p很少帧同步。除非是电竞属性很强的游戏

帧同步的一个难点是所有的信息和状态都在客户端上模拟理论上可以还原出一些不该让玩家看见的信息例如moba的全图和fps的透视
现代的游戏不会单纯的使用最简单的帧同步会有很多复杂方法策略的帧同步来规避
优点
1.带宽要求低仅同步指令
2.解决确定性问题之后开发效率很高
3.可以做一些对打击操作非常敏感精确的游戏
4.方便做游戏录屏

缺点
1.保持一致性很难
2.难以防止全图挂这种问题
3.如果没有服务器快照断线较长时追赶问题会比较严重

State Synchronization




核心思想是不会同步整个宇宙。
每个玩家只会提交自己部分的信息和部分的状态每个玩家自己模拟自己的世界。
服务器会模拟一个完整的全宇宙只会把部分的信息和当前玩家相关的信息发给对应客户端
放作弊的能力会好一点点
Server最大一切指令以服务器优先级最高
Authorized是这个玩家对于本身local的操作
Replicated其他玩家看到的这个玩家的复制品依赖于服务器传输的信息
玩家1与玩家2客户端看到的情况
玩家1:开火发送服务器
服务器玩家1开火广播所有客户端
玩家2收到通知玩家1开火


服务器通知每个客户端重复玩家1炮弹的运动

服务器判定击中了一个单位广播给所有客户端
状态同步核心思想
每个人提出自己的动作整个世界的核心业务逻辑由server完成。server产生的结果与client提出的动作都会被同步给所有客户端。
并不要求所有的客户端保持高度一致性只需要服务器做出判断。
状态同步只同步对于客户端需要的信息即一个感知范围内的信息(AOI算法)
有个问题是玩家A如果自己需要操作如往前走依旧需要等待服务器的确认这就会造成非常大的延迟导致操作不顺手。
1.客户端预测
2.服务器校验

根据客户端预测提前移动服务器校验没问题则保持不变
由于RTT和一个command frame的延迟会导致客户端永远比服务器超前
守望先锋估计一个RTT约160ms半个RTT 80ms一个command frame 16ms(刷新率60帧每秒)则客户端永远往前预测1680ms等服务器消息回来后进行对齐对齐是个插值的过程尽可能使移动变得平滑
client本地一个消息发出到从server回来接收可能长达上百毫秒本地可能已经跑了好几帧此时会把本地的每一次预测和每一个状态全部buffer到一个序列帧里。当server的每一个信息回来时会和过去的信息进行检验。因为从server回来的信息是经过了半个RTT时间的传输对于client接收的瞬间是过去的信息。
如果和server的校验信息不一致则以server的信息反向校准
从client角度看会有做了某件事但被校准回退的情况发生client需要一个ring buffer存储在过去几帧的数据当发现校验问题时ring buffer之后的数据全部无效重新算一遍
online游戏很常见对网速慢的玩家不利因为对世界的更新不及时操作反应不如网速快的玩家
丢包问题
1.server会把用户的输入用一个ring buffer存储起来会存储好几帧的输入
2.如果在一定时间内接收不到用户的输入有时候会自动把过去的最后一次操作进行复制(如跑动过程中断网在其他客户端展示的是扔在一直跑)
3.不同游戏有不同的处理丢包策略

number of players反了
帧同步适合注重打击感对抗感竞技类的游戏。对引擎的要求很高需要引擎的核心逻辑业务确定性非常高
状态同步适合网络本身比较复杂不太稳定并且游戏业务比较复杂。以及游戏的参与者非常多
现代主流引擎大部分能实现状态同步实现帧同步通常需要自己的引擎团队专门定制。

标签:
声明:无特别说明,转载请标明本文来源!