Unreal 学习笔记(四)
网络同步概述
拓扑结构
游戏中的网络同步有如下几种常见的拓扑结构:
- Peer2Peer:每个客户端和其他所有客户端互相通信。于红警等早期游戏采用,当人数变多时拓扑结构过于复杂。
- ListenServer:一台客户端作为主机,运行一个ListenServer,其他客户端与其通信(如 MineCraft 局域网联机),也是十分常用的拓扑结构,但当人数过多时会导致主机不堪重负。
- Client-Server:一个专用服务器(Dedicated Server)或服务器集群来同步各个状态
同步信息
- 输入模块:同步控制流
- 核心逻辑模块:同步事件流/状态流
- 输出控制模块:同步渲染指令流
- 输出模块:同步视频流(云游戏)
常用的是帧同步(同步控制流)、状态同步(同步事件/状态流)。
帧同步模型
核心理念:输入模块的输入给定时,同样的客户端其他模块的输出都是确定的。
不同的客户端把输入发送给服务器,服务器逐帧计算,将Frame N的数据打包后的一致性输入返回给客户端。客户端再通过确定性逻辑计算得到相同的输出画面。
参考资料:帧同步LockStep:原理与实现
浮点数问题
Q:在不同平台上,浮点数计算精度不一致。
解决方案:
- (临时方案)限制浮点数精度,取高N位
- 采用定点数计算
Q:定点数开放和超越函数如何实现?
A:泰勒展开后查表
Q:定点数随机函数?
A:线性同余生成伪随机数
参考资料:Emulating Double Precision on the GPU to Render Large Worlds - Godot Engine
逻辑一致性
- 基于整数和定点数,算法一致来实现逻辑
- 表现和逻辑分离,表现层不可修改逻辑
- 注意多线程不确定性
模型的改进
古典同步模型下,服务器需要收到所有Client的ACK才发Frame N+1;现代同步模型则遵从一套自己的复杂协议。
断线重连问题:短单局可以直接追帧,长单局需要结合状态同步,采用内存快照同步技术。
状态同步模型
状态同步的服务器种类
设 为实际游戏状态集合,只需保证各个客户端持有的 即可。包括三种实现:
- 仲裁服务器
- 游戏服务器
- 权威服务器(UE实现,与玩法弱相关)
仲裁服务器:客户端处理主体逻辑,服务器只维护极小的部分状态逻辑,如赛车游戏等。
权威服务器:客户端只有一小部分模拟逻辑,即在 Dedicated Server 或 Listen Server 维护了完整的游戏状态,是游戏服务器的一种特例。大多数 FPS 游戏都采用这种方式。
事件冲突
事件冲突:如两个玩家拾取同一个物品。
- 可以单点仲裁解决,服务器知道这两个事件肯定是有先后顺序的。
- 但是存在延迟问题,可以考虑用回溯到发生当时进行判断。
- 采用NTP算法同步逻辑时间:时间同步协议NTP
状态优化
- 客户端插值
- 航位预测
- 视觉掩饰(前摇、后摇)
同步协议的选择
一般都选 UDP。TCP太慢了,归功于重传机制与不再适用于弱网络的RTO(超时重传时间)计算策略。
因此开发了RUDP(Reliable UDP)等协议,一种实现方法是RUDP-ARQ(自动重传请求),实现简化版TCP协议;另一种方式是RUDP-FEC(前向冗余纠错)
TODO: 等计网结课了有空整理一下
FPS 游戏系统概述
武器系统
种类、槽位分类略。
程序逻辑:立刻命中(InstantHit)、投射物(Projectile)
弹道模型:
- 主视角角度
- 后坐力(最小值+连发数*递增系数,达到最大值后不再增加)
- 连发数
- 精准度
- 散发度
主弹道子弹射出方向=主视角角度+后坐力+精准度+散发度
特效:维护一个状态机管理开火、停止开火等状态的转换