I'm working on a 3D web game with client-side prediction, etc. I have implemented interpolation for my entities, but it seems a bit laggy sometimes even on localhost. First I will describe the algorithm, and then I will describe the problem.
Interpolation algorithm:
SERVER sends to all players (at 20 ticks per sec):
1.1) positions and rotations of all players
1.2) server time at the moment of sending this data (for example
serverTime == Date.now()
(it is calculated a little differently, but the value is roughly the same asDate.now()
; the error is 20 ms), that calculates every server tick)CLIENT receives all data and:
Saves received
serverTime
to global variable namedlocalServerTime
Pushes player's positions and rotations to their buffers (f.e. player1 has
buffer1: { time: number, position: Vector3, rotation: Vector2 }[]
, so we push received(from server) player1 position and rotation to the buffer1:buffer1.push({ time: localServerTime, position: receivesPlayer1Pos, rotaiton: receivedPlayer1Rotation })
CLIENT executes local game loop and changes
localServerTime
:localServerTime += deltaMs
CLIENT interpolates all other players positions and rotations like this:
We will interpolate players with offset == 100:
INTERPOLATION_OFFSET_MS = 100
, so find current lerp time:currentLerpTime = localServerTime - INTERPOLATION_OFFSET_MS
For all other players:
I will consider
player1
: getplayer1
's buffer:buffer1
and get state interpolate FROM(stateInterpolateFrom
) and state interpolate TO(stateInterpolateTo
) ( we will find this two states bycurrentLerpTime
, sostateInterpolateFrom.time < currentLerpTime
andstateInterpolateTo.time >= currentLerpTime
).Then we will find alpha(number, that is in range 0-1):
alpha = (currentLerpTime - stateInterpolateFrom.time) / (stateInterpolateTo.time - stateInterpolateFrom.time)
.Finally, i will interpolate position and rotation:
player1.position = lerp(stateInterpolateFrom.position, stateInterpolateTo.position, alpha)
, same for rotation
My problem here is the following: sometimes I have small lags that arise for some reason. I read that I need to synchronize time; I read a bunch of articles about entity interpolation, and the general principle is described there, but I did not find an algorithm about time synchronization anywhere, so I am asking for help.
I realized that the matter is in the localServerTime
, I calculate it incorrectly, but I don’t understand what exactly needs to be done, how to calculate it. If anyone has any relevant articles to put things in place, I would be very happy if you share them.
P.S. On the client I have variable syncedServerTimeMs
, when player connecting to the server, server send data: { serverTime: number, serverTick: number}
and client calculates syncedServerTimeMs
, so I can exactly say the serverTime when I need on it. In the client loop I update syncedServerTimeMs
: syncedServerTimeMs += deltaMs
, maybe I must use this variable somehow?