帧同步,服务器可以不起tick定时器吗?

服务器收到某客户端消息后立马转发给各个客户端,帧id由各个客户端自己控制自己合并帧,这样是否可行?
举个例子:客户端A在第六帧后50ms收到B的第7帧,60ms收到C的第7帧,70ms收到D的第7帧…。
感觉客户端很不好处理,A或E收到BCD帧数据的顺序都不好确定,有做过类似的帧同步么?

你这不是帧同步的做法啊,帧同步的每一帧是由服务端发过来,每一帧都包含了各个客户端在这帧的输入。比如你收到了服务端的第七帧,那么这帧数据就已经包含了客户端a,b,c的输入。不会发生先收到b的第七帧,下一帧收到c的第七帧

所以帧同步必须得服务器起定时器接收客户端消息然后定时转发吧。
我们服务器就给了个收到立即转发的接口,其他全部客户端自己处理,说也能实现帧同步,惊呆了,所以问下有没有人这样做过。

不是啊 帧同步就是客户天主动发起的 服务器不要定时器 出现各个客户端帧不同就要重发

服务器收到客户端消息直接转发,客户端自己合并帧数据吗?

是客户端自己组装帧数据,一个帧只会接收一个客户端的操作,其他客户端的操作推到下一帧再派

以上是我们之前的项目用的方法不是权威的 :smile:

哦,一帧只有一个客户端的操作好像不适合我们项目 :grinning:

这样的话还是要锁定帧,服务器等到一帧时间后再派发其他客户端的操作,不会存在某一帧执行快另一帧执行慢

你把一个简单的帧同步复杂化了。没考虑玩家的网络状况,手机性能

所以你的服务端根本不懂什么帧同步,而且你们做的也不是帧同步。我猜测得出你们的做法是,每个客户端把自己的游戏数据,如自己玩家的位置,生命状态,攻防等这些数据发给服务端,服务端再转发给每个客户端,其它客户端收到你的数据,就现实你的玩家的位置和状态。这和帧同步一点都不沾边。你们在白费力气。帧同步要遵守一个基本定则,既:“相同的输入在相同的时机得到相同的结果”。搞帧同步最起码要前后端都懂的人参与才行,现在你们在前后端互相甩锅,搞不成。我是搞前后端搞了一年,打了大量的日志验证,填了各种坑才把帧同步游戏搞出来的。这技术不是那么容易

有点疑惑,你们这种方法发一帧转一帧,真的能确保客户端同步吗。怎么保证在每个客户端所有的客户端的操作都发生在同一时机呢,而且没有逻辑帧的概念。

那倒不至于你说的,你说的是状态同步了,只是我们服务器不控制逻辑帧率,收到任意消息立即转发,其他全由客户端处理。

哪你们没有帧序号的概念啊。比如每个客户端, 第一帧:C1,C2做了什么操作,第二帧 C1,C2做了什么操作…。每个客户端收到的每一帧的所有操作都相同,才有办法算出一致的结果。你们现在收到就立即转发,没有游戏帧序号的存在,没一帧的输入是什么都不知道,算不出一样的结果啊。所以这才需要服务端定时收集所有客户端的输入封装在帧数据里,把帧序号排序好发给客户端,客户都再基于服务端发过来的帧运行游戏才行。

是的,我认同你说的,像我们这样的服务端机制,每个客户端都在制定自己的帧序号了,很头痛。

你们的做法,这不是定制自己序列帧那么简单的问题。
打个比方如果两个客户都C1,C2对战,按你们的做法客户都自己定帧号转发,如果C1,操作了10次,并且转发了10次,C2只操作了一次,转发了1次。这时每个客户都都收到了C1的10次操作和C2的1次操作,然后客户端按帧号重组序列帧。那么问题来了,这游戏是运行了10帧(按c1)呢还是只运行了1帧(按c2),如果c2的唯一操作是发生在c1的10帧之后的,那么这帧算第1帧呢,还是第11帧。还有如果c1和c2什么操作都没有,一帧都没发,那么这游戏是不是就没有在运行(因为一帧都没运行过)。

所以你们的做法和帧同步一点都不沾边

改引擎. 不改实现不了;

你好像错了,你其实只做了“转发”,并不是帧同步,状态同步更复杂。乐观帧同步,只有服务端tick,服务端50ms tick一次,客户端接收后更新逻辑,客户端的帧+1。这里说得帧是逻辑帧,不是客户端的渲染update,因此有两个意义上的update,一个是逻辑帧,是服务器来tick的,一个是客户端的update更新自己逻辑。在此基础上,做“预测”、“回滚”功能。如果你想设计p2p,其实也是要设计一个“客户端”代理的。

这位兄弟说的没错,帧同步就是这样设计。不过帧的编号最好由服务端编好,打进帧数据里。客户端收到每一帧时就能知道这是第几帧,特别是用udp通信的时候,不一定就是先发先收到,这时由客户端自己根据收到帧数据的先后顺序编号的话,服务端发送了1,2,3帧,客户端可能收到1,3,2帧,再重新编帧号的就错乱了。

了解,还有个问题请教下,同一逻辑帧里面,A做了向下再往左两个动作,这两个动作间隔时间50ms,每个逻辑帧间隔100ms,在A自己看来先往下走了一段再往左,但在其他客户端看来A往下和往左是同一帧过来的,这种情况怎么处理呢? A在同一逻辑帧中只保留最后一个操作么? 还是A也得等这个逻辑帧返回后再执行操作,如果等待帧返回的话感觉A自己延迟比较大,不跟手。