Javascript 多人浏览器游戏:导致抖动和跳跃的线性插值
我正在开发一个浏览器多人游戏,其中每个客户端插入(线性)服务器发送的实体帧。在高帧速率(>30fps)时,它看起来不太糟糕,但在低帧速率(<30fps)时开始抖动,并冻结、跳跃和非常低的帧速率(<10fps)。我想降低帧速率,而且我知道这是可能的(请参阅以10fps发送更新) 这是我使用的基本算法:Javascript 多人浏览器游戏:导致抖动和跳跃的线性插值,javascript,interpolation,multiplayer,motion,linear-interpolation,Javascript,Interpolation,Multiplayer,Motion,Linear Interpolation,我正在开发一个浏览器多人游戏,其中每个客户端插入(线性)服务器发送的实体帧。在高帧速率(>30fps)时,它看起来不太糟糕,但在低帧速率(
- 服务器以帧速率(比如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;