帧同步技术(二)

第一篇文章中我们讲了帧同步的核心:如何保证各个客户端的一致性。保证不同客户端各自计算的结果都相同就能确保帧同步玩法的正确有效,但如果服务端消息没下来前整个客户端画面一动不动,体验是非常不好的。在确保一致性的前提下做一些预表现以及降低网络传输的延迟能给到玩家更好的体验。这篇文章主要讲这方面的一些优化,另外还有关于不同步问题的定位排查、防止客户端修改作弊、断线重连与网络消息堆积时的一些处理方案。

UDP传输:TCP传输因为在底层做了各种关于可靠性及稳定性的处理(详细可见《计算机网络——传输层:TCP与UDP》),所以延迟会比较高。而在帧同步战斗中,操作需要上行到服务器然后经过转发到达到各个客户端才能推进真正的逻辑,低延迟对玩家操作体验非常重要。而帧同步战斗这种频繁(1秒30帧)的传输小量(只转发操作)的数据,用UDP也是很有优势的。在相同的网络环境下,UDP可以在一个逻辑帧内完成来回的,延迟在33ms以内,而使用TCP至少要3-4个逻辑帧才能完成来回,延迟在130ms以上。

使用UDP传输需要自己处理乱序和丢包的问题。帧同步战斗中,服务器定时派发的帧数据本来就是有序号的,所以乱序到达的问题只要缓存起来按顺序使用就可以了。而丢包的问题我们可以采用冗余传输来尽量避免。服务器一次下行中不仅带上当前第n帧的信息,还可以带上n-1,n-2或更多的冗余信息,这样只要不是连续丢多个包,都能保证客户端最终收到连续的帧信息。如果客户端当前在等第t帧, 但已经收到第m帧的信息,m-t的差值大于一定程度,就认为已经连续丢了多个包,这个时候靠冗余信息已经拼凑不回来完整的序列了,就需要利用TCP重新请求缺失的帧,服务端用TCP把客户端请求的帧信息重新补发。利用TCP来做请求重传虽然速度慢,但可以保证一定能收到。具体流程图如下:

Continue reading

帧同步技术(一)

关于帧同步技术原理及实现方案网上已经有非常多的文章介绍了,但做《月夜狂想曲》的帧同步战斗时还是有遇到很多具体的细节问题,也做了很多相关处理,在这打算分两篇文章记录一下。第一篇主要讲客户端如何保持一致性,会遇到哪些问题以及怎么处理。第二篇主要讲通过哪些改进可以让帧同步有更好的游戏体验。

帧同步的原理是,服务器只负责收集指令,然后以恒定帧率(例如30帧1秒)转发指令,真正的游戏逻辑由各个客户端各自计算,客户端要等到服务器派发的指令才能推进逻辑,没有收到指令时逻辑是暂停的(LockStep)。帧同步最重要的是确保各个客户端在不同硬件不同平台下各自计算游戏逻辑结果都是一致的。在Unity中为了达到这个目标,我们需要解决以下问题:

随机数:Unity自带的随机数因为有可能会被物理系统,粒子系统,UI系统,第三方组件等各种模块使用,我们是无法保证他在不同客户端下每次都能取到统一的随机数的。这就需要我们自己实现一套自己控制的随机数发生器,关于如何实现随机数的算法,之前写过一篇文章介绍《随机数生成算法》。在有可控的随机数发生器后,我们需要查找项目中所有用到随机数的地方,判断该流程是逻辑相关需要被统一接管的,还是表现相关可以由各个客户端自由决定的,从而使用不同的随机数发生器。 目标就是确保逻辑相关的流程下在各个客户端下都能取到同样的随机数。

Continue reading

游戏开发安全问题

这几年开发Unity手游时,陆续会针对安全问题做一些处理,在这里分享一下我们的一些做法。我将安全问题分为四大块,每一块都有很多可以深入挖掘的点,也有专门做安全的部门或第三方支持。这里更多介绍的是一些项目组会用到的安全策略。

—— 数据安全

数据安全首先需要处理的是内存安全,面对大量的内存扫描,内存修改工具,如果项目内的核心数据是裸放在内存中的话,肯定避免不了被改属性或者锁血这些问题。 内存安全我们的具体做法是把关键数据int或float的4字节随机映射到一块36字节的空间内。

Continue reading