2025年chronyc 手动同步命令(chrony 手工同步)

chronyc 手动同步命令(chrony 手工同步)p 经过前一篇的概念梳理水贴后 本篇文章将正式开始我自己理解的帧同步代码逻辑 p 虽然网上已经有大部分文章有讲解过相关流程 无外乎就是预测 输入 回滚 追帧修正 那这几个概念具体是怎样的呢 我试着用点直白的语言来解释一下 由于内容很多 所以我将同步流程一章改为上下两篇进行梳理

大家好,我是讯享网,很高兴认识大家。



 <p>经过前一篇的概念梳理水贴后&#xff0c;本篇文章将正式开始我自己理解的帧同步代码逻辑。</p> 

讯享网

虽然网上已经有大部分文章有讲解过相关流程,无外乎就是预测,输入,回滚,追帧修正。

那这几个概念具体是怎样的呢,我试着用点直白的语言来解释一下。

由于内容很多,所以我将同步流程一章改为上下两篇进行梳理。而且文章中很多地方都有极大的优化空间(给后面的日记水内容用),所以大家看看思路就好了,不要把我的日记当作教科书。

前言:

之前已经反复讲过了,这里再提一次,如果一个游戏流程,没有任何未知输入的干扰,那么我们完完全全可以知道这个游戏上下五千年的历史(当然不要在意计算时间啥的)。之所以提一嘴未知输入,是因为我们的本机的输入是已知且确定的,而确定的已知的输入仍然不影响我们对未来五千年的预测。

另外,虽然游戏看起来充满了随机性,但其实所有的随机性其实本身也是有一个固定的随机数种子进行控制的。

例如最常见的随机数生成器。

讯享网

只要种子是一样的,那么这个随机数生成器生成的随机数序列就是固定的了,当然这些数字本身看起来也是很随机的,这也就是所谓的伪随机。而对于一款帧同步游戏来讲,我们必须要使用一个可控的,设备无关的随机数生成器,而不能想当然的使用每个语言自己的那一套。

有了以上这些前提,我们才可以说,我们能够知道这个游戏五千年后会是怎样的,只要你给时间。

由于,没有网络=不会产生未知的输入=游戏状态可预测=我们在跑单机。所以60FPS游戏,1个渲染帧的时间间隔(16.6667ms),足够我们处理逻辑和渲染了。这也是让我们的帧同步游戏可以在网络不佳的情况下看起来很流畅的基石。(如果已经适当优化后,跑没有接入网络的网络游戏都会卡的话,要么降低FPS,要么这边建议还是洗洗睡吧,这潭水很深的……)

 

输入:

输入的概念已经提到过很多次了,多数情况下,我们会收到各式各样的操作,因为一款多人游戏除了玩家自己,最起码还有另外一个玩家,他们的操作在任何时候都有可能被广播给自己,而另外,我们并不能保证我们所有的操作都已经被服务器认证了。(有各种可能性,例如丢包,超时,或者我们将提到的一种情况)

由于我们不能保证所有客户端和服务器的所处逻辑帧数是相同的(这是很常见的现象,因为性能,网络延迟等等因素,都会产生),所以为了能让我们的程序能够正确合理的处理输入,我们需要有一个机制来管理输入保证不会错乱,也尽可能地不会漏操作。

早期地帧同步游戏,例如各种经典地RTS游戏(星际争霸,魔兽争霸),采取了一种策略。既然我不能所有人都在同一个节奏上,那么我就设计一个机制来实现这个机制。这个机制就是一个广播机制。由于所有客户端每时每刻都会产生大量操作,这些操作会发给服务器,服务器经过操作收集和整理(当然,也有比较懒地服务器不做这事)后再广播给所有客户端,所以这里有一个基准值,就是服务器地消息帧,以服务器下行消息为基准,所有客户端都可以自行往前跑,并且将合在一起下行的操作一起进行执行,然后客户端步进到服务器告诉的终点就把步进逻辑停下来,等待服务器下次发送消息过来。而如果某个客户端经过计算,发现只靠步进需要追的帧距离目标差太远了,那这台客户端可以通过一些策略来进行追赶(比如提高单次步进的帧数,或者缩短逻辑帧之间的时间间隔)

这种做法有很明显的好处,客户端之间的波动,不会导致每台客户端之间有很大的不同步(这里的不同步指的是画面,或者说游戏进程,而非数据上的不同步)。而服务器收集操作下行给客户端,也保证了所有客户端收到的消息的一致性,单台客户端不需要去管某个操作是否发给了其他客户端,反正一切都是客户端说了算。 另外,需要注意的是,没有操作也是一种操作。(如果没有操作就啥也不发,那请问该如何区分是真没操作,还是操作因为各种原因丢失了呢?)

而这个做法明显的缺点也显而易见。客户端流畅不流畅,一切取决于网络状况,只要有点延迟,就很容易感到卡顿。这点很容易理解,因为客户端跑不跑跑多少,其实都是服务器通知的,客户端无法违背服务器,所以一旦没有服务器的指令,客户端就会卡在那里不动了。玩过那个年代RTS游戏的人肯定看到过这种卡顿。

预测:
这种体验给洪荒时代的玩家来说完全不是事,能联网对战了,还要啥自行车呢?但现在肯定不够了,所以我们需要设计一种更优化的算法。


讯享网

以下内容就全是我自己的摸石头过河得到的理论和设计了,如果有和行业标准不一致,或者有更成熟方案的做法,是必然的。毕竟这文章是我的开发日记,不是行业教科书。

再次回到我们帧同步的前提,我们的状态在初始状态和输入状态全都确定的情况下,无关设备,一定能算出这个场景的发展历史。所以,假如我们在把指令发送给服务器后,就先在本地把操作执行了,假如下一次服务器同步的时候,正好只有我们自己的这份操作,那岂不是丝滑的不行,什么都不用动就已经成为了应该成为的状态了?简直就和跑单机游戏一般。

这也就是所谓的预测,将自己已知确定的操作,配合游戏状态,赌一手这段时间没有其他的输入,那直接就可以无损的将游戏进程进行推进了。

讯享网

回滚与快照:

当然既然是网络游戏,前文那种理想情况大概率是小概率事件,必然会出现有操作会打乱我们原来的操作序列,甚至会导致我们原来合法的操作不合法的情况。(比如,我在第114帧进行了发射子弹的操作,击杀了一个怪物得到了514分,但经过服务器的消息广播,却发现对面在110帧的时候,就已经进行发射子弹的操作,并且击杀了这个怪物,那我自己的操作就相当于打空了)所以我们就需要将我们的游戏状态回滚到第一个与服务器不一致的地方。

那么问题来了,我们怎么知道那一帧的状态是怎样的呢?

我采用了这么一种做法,为了记录一帧中的所有状态,我们可以对这一帧的游戏状态制作一个快照,我们可以通过这个备份,我们可以重塑这一帧游戏的所有状态。

至于快照怎么做,最简单的,直接把当前游戏状态管理的数据层做一个深拷贝就好了。

 

不过实际上,由于不是所有东西都是游戏状态数据,有些可能只是我们的一些缓存,有些可能是一些解析后的常量配置,而且在编写的时候,我们很可能并非一个单独的数据中心,而是由大量的逻辑实例组成的,而每个实例自己持有了描述自身的关键数据。

所以我个人习惯的快照是如下的做法。

讯享网

(以上的快照做法仍然有可优化或者说必须要进行的优化,未来在后续的日记中会做解释)

当我们有了快照以后,就可以瞬间将游戏状态恢复到对应的快照状态,这为我们进行游戏回滚提供了可能性。

回到开始,我们的目的是让游戏流程从产生操作矛盾的第一帧,然后将所有的操作重新插入操作序列进行一次应用,然后将游戏状态恢复到那一刻。所以一个比较符合直觉的认知就是,在这之前的前一帧,我们的所有预测都是正确的,所以只需要回滚到这个操作的前一帧就可以了,也就是说只需要应用这个前一帧的快照即可。

但另一个问题又来了,我怎么知道从哪一帧开始有矛盾呢?

一个比较符合直觉的做法是,我每一次预测都把这一帧的快照拷贝下来不就成了。确实,这么做的确能够保证我们想回到哪里回到哪里了。

 

帧同步流程上半篇的内容就先到此为止了。至于追帧以及后续的一些优化相关的内容,敬请下回分解。


小讯
上一篇 2025-06-17 07:41
下一篇 2025-06-16 17:38

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/194161.html