I have a game server which, for testing purposes, is updating once per second, or 1hz so I can correctly implement client-side prediction. Everything is running locally at the moment so there is no lag issues to deal with, but this setup replicates potential packet loss, or if the server somehow is behind on processing.
I am using Unity for the client. I have a tunnel where the position is updated on the server and then broadcast to each client each tick (once per second). The client simply then lerps between its current position, and the new position received from the server, and this seems to work nicely.
However, as I have set the tick to 1hz, there are unexpected results where the position seems to pulse, rather than smoothly transition. An example can be seen below.
It can perhaps be seen more clearly without lerping
I have tried constantly increasing the tunnel's position in the client, but if it's moved too far in the client, once the server's position is received, it is snapped back to that position which creates some weird rubber-banding like effects even though there is no lag.
How can I determine how much to move the tunnel in the client to create some seamless movement, even when the tick rate is so low? Baring in mind this movement is variable, so it can move faster/slower at times so the movement in the client cannot be a fixed number.
Yes, I can just increase the tick rate which gives smooth movement, however, there is no lag to account for as it's all local so I am just preparing for when I move the server to actual hosting.
Instead of lerping between the current position and the received position, should I be trying to lerp between the current position and the next received position?
Lerp:
Vector3 currentPosition = transform.position;
Vector3 newPosition = new Vector3(currentPosition.x, currentPosition.y, tunnelPositionZ);
transform.position = Vector3.Lerp(currentPosition, newPosition, Time.deltaTime);
DMGregory's solution attempt:
If I decrease the 1.0f
for the blend
variable, the tunnel will move very slowly and then jolt forward when a snapshot is received. Decreasing the 1.0f
to around 0.1f
seems to align the speeds but there is still a noticeable jolt.
I'm using the same velocity for the currentPosition
and newPosition
because the velocity never changes.
float dT = Time.time - latestSnapshot.arrivalTime;
float blend = Mathf.Clamp01(dT / 1.0f);
Vector3 currentPosition = transform.position;
Vector3 currentVelocity = rigidbody.velocity;
Vector3 newPosition = new Vector3(currentPosition.x, currentPosition.y, latestSnapshot.tunnelPositionZ);
Vector3 newVelocity = new Vector3(currentVelocity.x, currentVelocity.y, latestSnapshot.tunnelVelocityZ);
Vector3 velocity = Vector3.Lerp(currentVelocity, newVelocity, blend);
Vector3 position = Vector3.Lerp(
currentPosition + velocity * dT,
newPosition + velocity * dT,
blend);
transform.position = position;
current = Lerp(current, target, blend);
. This is good for chasing a continuously changing variable, but not for discrete periodic updates. (And the deltaTime correction used here is incorrect) Another user had a similar issue recently — does this previous Q&A help you at all? \$\endgroup\$blend
variable, the smoother the movement becomes.0.01f
seems to be nice for consistent movement, however I don't know if the client is now ahead of the server or vice-versa. \$\endgroup\$