我正在开发一款多人在线浏览器游戏,其中每个客户端使用线性插值来处理服务器发送的实体帧。当帧率较高(> 30fps)时,效果还不错,但当帧率较低时(< 30fps),会出现抖动,并且在非常低的帧率下(< 10fps)会出现冻结和跳跃。我想降低帧率,我知道这是可能的(参见Brutal.io 以10fps发送更新)。
以下是我正在使用的基本算法: - 服务器以帧速率(例如10fps)发送更新。 - 客户端以帧速率(例如60fps)呈现游戏。 - 客户端不直接更新屏幕上的实体以匹配服务器的数据:这看起来很抖动。 - 相反,它使用线性插值函数来平滑处理服务器更新之间的帧。 - 在10:60fps的例子中,客户端将呈现6个帧以创建平滑的动画。 - 它通过测量服务器更新之间以及客户端渲染帧之间的差异来实现这一点。 - 然后,它通过将客户端delta除以服务器delta来获取乘数。 - 接着,它调用线性插值函数,使用屏幕位置、服务器位置和乘数来生成新的屏幕位置。
此片段不包含特定代码,但应该足以演示基本概述(请参见代码中的注释)。
如上所述,这会导致运动中的抖动和跳跃。我是否做错了什么?如何使此运动平滑?
以下是我正在使用的基本算法: - 服务器以帧速率(例如10fps)发送更新。 - 客户端以帧速率(例如60fps)呈现游戏。 - 客户端不直接更新屏幕上的实体以匹配服务器的数据:这看起来很抖动。 - 相反,它使用线性插值函数来平滑处理服务器更新之间的帧。 - 在10:60fps的例子中,客户端将呈现6个帧以创建平滑的动画。 - 它通过测量服务器更新之间以及客户端渲染帧之间的差异来实现这一点。 - 然后,它通过将客户端delta除以服务器delta来获取乘数。 - 接着,它调用线性插值函数,使用屏幕位置、服务器位置和乘数来生成新的屏幕位置。
此片段不包含特定代码,但应该足以演示基本概述(请参见代码中的注释)。
var serverDelta = 1; // Setting up a variable to store the time between server updates
// Called when the server sends an update (aiming for 10fps)
function onServerUpdate(message) {
serverDelta = Date.now() - lastServerFrame;
}
// Called when the client renders (could be as high as 60fps)
var onClientRender() {
var clientDelta = Date.now() - lastUpdateFrame;
// Describes the multiplier used for the linear interpolation function
var lerpMult = clientDelta / serverDelta;
if (lerpMult > 1) { // Making sure that the screen position doesn't go beyond the server position
lerpMult = 1;
}
lastUpdateFrame = Date.now();
...
// For each entity
// ($x,$y) is position sent by server, (x,y) is current position on screen
entity.x = linearInterpolate(entity.x, entity.$x, lerpMult / 2);
entity.y = linearInterpolate(entity.y, entity.$y, lerpMult / 2);
}
function linearInterpolate(a, b, f) {
return (a * (1 - f)) + (b * f);
};
如上所述,这会导致运动中的抖动和跳跃。我是否做错了什么?如何使此运动平滑?