今天花了点时间写了一个帧同步,看起来效果还是不错,如果网络极好的情况下。
其实所谓的帧同步,不过就是让客户端传输数据给服务器一些核心数据(比如 位置、角度、操作),然后再广播给其他客户端,最后客户端渲染的画面就差不多就可以了。
不过在现实的情况,总是需要面对各种各样的情况。
TCP or UDP ?
目前来说,使用 TCP 协议来进行通讯,是没有丢包的风险的。但也正是因为 TCP 本身是在不可靠的网络环境进行可靠的传输,一旦发生丢包,就需要进行重发,而重发这段时间就会导致包堵塞,从而导致性能损耗。
而使用 UDP 的技术,并没有协议上导致堵塞的问题,同时因为无需在协议内进行校验,所以性能损耗非常低。相反则需要面对可怕的丢包问题,这就意味着如果程序处理不当,一个小小的丢包都可以造成程序的崩溃。
两个选择有好的也有坏的,不过 TCP 比 UDP 可靠,所以不着重讲 TCP 。
必定遇到的问题
- 延迟
延迟俩协议都会遇到的问题,基本上只能从预测来进行缓解了,而且仅限于中度延迟(≤90ms)时才会有一定的作用。
预测上只能判断个大概,并不能保证每次预测都对的。
- 丢包
丢包比延迟更加头疼。如果程序处理不当,稍微丢一些数据,都有可能导致崩溃。
在比较轻微的情况下(2% - 6%),可以尝试忽略一些数据,也可以通过算法来尝试计算原本应该获取的数据。
严重时(20% - 40%),基本上是需要服务器重发,或者直接丢弃等待服务器下一帧的数据。、
更多的,直接当断线都可以了。
可以通过压缩数据来减少丢包的可能性。
- 乱序
这个主要体现在 UDP 协议,体现在旧的数据包比新的数据包晚到。
处理不当可能会导致 实体回溯、状态滚回 等等问题。
处理上加个时间戳来校验,只刷新比当前状态新的数据即可。
我个人技术方面问题,我没有给实验程序写保持可靠性的算法,可靠性方面是靠 TCP 的重发保持的。
已经可以稳定实现帧同步,可能是因为调用方法太多,tickrate 高于 80 之后就没有什么效果了,低配的电脑可能更低。
也不排除时因为 WinForm 性能开销大导致的。
动图预览
源代码:https://cnyg.xyz/file/projects/test_framesync/test_framesync.zip
使用 Visual Studio 2022 进行编译
里面的 <项目>/bin/Release/ 文件夹也有已经编译了的可执行程序。
服务端需要使用 Windows 7 ESU 或以上的系统进行
客户端使用 WinForm (.NET Framework 4.5.2)
服务端使用 .NET 5.0
通讯使用 TCP 协议
用 Cookie 保存: 别名、Email