- Unity版本(2020 3.34f1c2)
- Visual Studio 2019
游戏开发过程中经常会设计到时间的运算判定,比如开服时间,触发时间,倒计时时间等,所有的这些时间都要基于和服务器或网络对时后的网络时间为基准来计算。单纯采用本地客户端时间的话会导致通过修改本地客户端时间就能达到加速和调时间的目的。本章节通过深入学习网络对时,实现一套没有服务器也能正确网络对时的对时方案(如果有后端的话以后端时间对时为准即可,本人是出于不懂服务器开发所以才采用网络对时的方案)。
当我们开发多个国家的游戏的时候,为了确保时间的统一,这个时候我们就可以采用UTC时间作为时间标准,每个国家的时间戳计算标准都是统一的(不需要考虑时区问题)。
了解了UTC时间后,这里本人使用NTP服务来实现没有专属服务器时的网络对时。
NTP(Network Time Protocol)(网络对时服务)**
通过在网络报文上打「时间戳」的方式,然后配合计算网络延迟,从而修正本机的时间。
可以看到通过包含发送,接收,返回和返回接收时间戳的方式,我们可以计算出网络延迟从而做到正确的同步的网络时间
网路延时 = (客户端接收时间 - 客户端发送时间) - (服务器返回消息时间 - 服务器接受消息时间)
时间差 = 服务器接受消息时间 - 客户端发送时间 - 网络延时 / 2 = ((服务器接受消息时间 - 客户端发送时间) + (服务器返回消息时间 - 客户端接收时间)) / 2
当前同步服务器时间 = 客户端接收时间 + 时间差
网络对时方案:
- 使用阿里云提供的NTP网址作为NTP服务器
- Socket短连接方式获取NTP报文数据
- 当前同步网络时间 = 网络对时 + (本地真实运行时长 - 对时时本地真实运行时长
这里我把本地时间同步关闭,并修改时间从2022/07/22 00:06到2022/07/24/03:06时间
同步时间前:
同步时间后:
从上面可以看到通过NTP的对时后,我们成功获取到了网络的UTC时间。
当前同步网络时间 = 网络对时 + (本地运行时长 - 对时时本地运行时长)
可以看到我成功的通过网络对时和记录本地真实运行时间等信息成功计算出了当前网络对时时间。
接下来加入Unix时间戳概念。
当前时间戳 = 当前同步网络时间 - Unix时间戳基准时间(1970/1/1)
同步UTC时间前时间戳:
同步UTC时间后时间戳:
可以看到我们通过和Unix时间戳基准时间(1970年1月1月0时0分0秒)成功计算出了当前对时的UTC时间戳
- 同步网络对网络要求不高,可以采用UDP
- NTP报文里有服务器相关获得请求时间和服务求返回请求时间,通过这些数据的解析我们能计算出真实的网络时间
- NTP里的时间戳是基于1900年1月1日,而非像Unix时间戳基于1970年1月1日
- 本地最新网络时间需要通过记录对时时的运行时间来计算最新的当前网络时间
- 网络时间同步没必要一直同步,可以采用短连接在必要的时候同步一次