Answers:
我实际上尚未实现此操作(因此可能有一些我没有立即看到的问题),但我想我会尽力的。
您正在说的是这件事:
客户端A在T0发送输入
服务器在T1接收输入
所有客户都在T2收到更改
但是,在T2,使用客户端预测,客户端A现在处于适合T4的位置。
考虑服务器时间可能会很有用。它(可能)与插值的工作原理非常相似。
每个命令都随服务器时间一起发送。该服务器时间是在比赛开始时通过查询服务器滴答声来计算的,以补偿ping时间。在客户端上,您有自己的本地滴答计数,并且您发送的每个命令都将转换为服务器滴答(这是一个简单的减法操作)
同样,客户端总是渲染“过去”。因此,您假设客户端所看到的世界比服务器的实际时间晚了100毫秒。
因此,让我们用服务器时间(由S指定)重新说明您的示例。
客户端在服务器时间为S0的T0发送输入(我猜这实际上是“服务器时间减去插值时间的客户端表示形式”)。客户端不等待服务器的响应,而是立即移动。
服务器在T1接收输入。服务器计算出客户端在给定的服务器时间S0上的客户端权威位置。将其发送给客户端。
客户在T2处获得权威位置(仍然指定服务器时间S0)。客户跟踪过去事件的过去时间量(可能只是所有未确认的预测的队列)。
如果服务器在S0处发回的预测位置/速度/值与客户端在S0中存储的内容不同,则客户端会以某种方式进行处理。通过将播放器恢复到过去的位置,或者重新模拟先前的输入,或者可能是我没有想到的其他方式。
实际上,在github中有一个开源实现,展示了如何实现。看看Lance.gg
github仓库:https : //github.com/lance-gg/lance
客户端预测代码在称为的模块中实现 src/syncStrategies/ExtrapolateStrategy.js
除了外推,我上面没有提到两个概念:
客户端A始终领先于服务器-但这无关紧要。仅当服务器说报告的位置有问题时,才需要重新挂起客户端,这时客户端将重新运行自错误以来的所有更改并使用更正后的值,以使其状态兼容与服务器。
为此,客户端需要记住其过去的状态和过去的更新。这可能只是一些简单的值,例如位置,速度,方向等。服务器将定期发送确认,确认各种客户端更新是合法的,这意味着现在可以将其从客户端中忘记。但是,如果服务器报告更新无效,则客户端状态将回滚到该点,并且将来的更改将应用于该已修改状态。
Valve文章底部有一些其他链接值得一读-这是其中之一:https : //developer.valvesoftware.com/wiki/Prediction
t=4
)收到有关的信息是正确的t=2
,所以它会重置状态,t=2
然后重新运行更新以将对象从t=2
引入t=4
?