Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 多人浏览器游戏:导致抖动和跳跃的线性插值_Javascript_Interpolation_Multiplayer_Motion_Linear Interpolation - Fatal编程技术网

Javascript 多人浏览器游戏:导致抖动和跳跃的线性插值

Javascript 多人浏览器游戏:导致抖动和跳跃的线性插值,javascript,interpolation,multiplayer,motion,linear-interpolation,Javascript,Interpolation,Multiplayer,Motion,Linear Interpolation,我正在开发一个浏览器多人游戏,其中每个客户端插入(线性)服务器发送的实体帧。在高帧速率(>30fps)时,它看起来不太糟糕,但在低帧速率(

我正在开发一个浏览器多人游戏,其中每个客户端插入(线性)服务器发送的实体帧。在高帧速率(>30fps)时,它看起来不太糟糕,但在低帧速率(<30fps)时开始抖动,并冻结、跳跃和非常低的帧速率(<10fps)。我想降低帧速率,而且我知道这是可能的(请参阅以10fps发送更新)

这是我使用的基本算法:

  • 服务器以帧速率(比如10fps)发送更新
  • 客户端以帧速率(例如,60fps)渲染游戏
  • 客户机不会更新屏幕上的实体以直接匹配服务器的数据:这看起来很紧张
  • 相反,它使用线性插值函数平滑服务器更新之间的帧
  • 以10:60fps为例,客户机将在其间渲染6帧以创建平滑动画
  • 它通过测量服务器更新之间的增量(差异)以及客户端渲染帧来实现这一点
  • 然后,它通过将客户机增量与服务器增量分开得到一个乘数
  • 然后,它调用线性插值函数,使用屏幕位置、服务器位置和乘法器生成新的屏幕位置
此代码段不包含特定代码,但应足以演示基本概述(有关信息,请参阅代码中的注释):


如上所述,这会在运动中产生抖动和跳跃。我做错什么了吗?如何使此运动平滑?

插值必须介于两个服务器状态之间。您可以保留客户端上接收到的上一个X服务器状态的历史记录。每个服务器状态代表一个特定的帧

例如,假设您的客户端保持以下服务器状态及其帧:

state[0] = {frame: 0, ... };
state[1] = {frame: 10, ... };
state[2] = {frame: 20, ... };
如果客户端现在正在渲染第15帧,则它必须在
状态[1]
状态[2]
之间的中间插入位置。公式是

// prev=1, next=2 
let interpolatePercent = (clientFrame - serverState[prev].frame) / serverUpdateRate;
entity.x = interpolatePercent * (serverState[next].entity.x - serverState[prev].entity.x) + serverState[prev].entity.x;
在您的代码中,
lerpMult
很可能大于1,在这种情况下,您现在执行的是外推,而不是更难的插值


另外,您可能还想看看为浏览器多人游戏实现插值(和外推)的开放源代码库:

我想了解-在插值发生之前,您如何知道最终服务器帧是什么?换句话说,如何在一个值和另一个你不知道的值之间进行插值,而不造成滞后?嗯,好吧,你是说我的方法是使用前一帧的增量,用当前值进行插值?解决方案是存储“最后一个服务器增量”并使用它吗?@clabe45抱歉,忘了提到你了。请参见上面的^^^。@clabe45我刚刚尝试过:这会使它更平滑,但实体仍会每隔几秒钟跳转一次。但执行“最后一个服务器增量”不会导致明显的延迟吗?
// prev=1, next=2 
let interpolatePercent = (clientFrame - serverState[prev].frame) / serverUpdateRate;
entity.x = interpolatePercent * (serverState[next].entity.x - serverState[prev].entity.x) + serverState[prev].entity.x;