Hey everyone, I’ve been trying to figure out why a movement system I’ve been building is supper laggy feeling and I’m 99% sure it’s because of deltaTime. The default cube example in the getting started section of the netcode documentation just uses Time.DeltaTime so I thought this was the way to go. I assumed that the delta times would be corrected for the fact that the server runs prediction less times then the client.
But I wrote some code that allowed me to see the difference between the client prediction and the server prediction of my controller and they were way off. Curious I wrote a simple script that just added delta time to a float every time the prediction was run and boy was I surprised, a ran it for a bit my server accurately counted 31.36 seconds while my client counted 392.93 seconds. That doesn’t even make sense taking into account the fact that the server is running (I’m guessing) at a fixed 60 fps and my client is running at 90fps.
Is there a premade way to get a normalized/fixed delta time that will work for both? Or will I have to write a simple timer function to get it?
Generally any variable you want to apply prediction to should be synced between server and client. Prediction code is run more times on clients than the server.
I already have all the variables I need syncing through the server but to be able to accurately predict player movement I need a consistent delta time and for some reason the delta time on the client is wrong. Without this I would have terrible rubber banding.
I don’t need it to be exactly the same, just close enough that it doesn’t cause rubber banding when the server updates the player transform. What I’m currently trying to do is to use movement code similar to this: https://adrianb.io/2015/02/14/bunnyhop.html inside of a system running in the GhostPredictionSystemGroup. The game I’m building will have high movement speeds so it’s important that the movement is responsive and has as little lag as possible. Currently, I’m storing the velocity in a component on my player and it is networked through the GhostAuthoringScript. The problem is that the movement code on the server and the player are spitting out vastly different results for the same input because of the deltaTime variable being off for whatever reason. I was able to come up with a way to get the true delta time for the system then divide it by the number of time the system was updated the last frame to get a useable value. It removed most of the rubber banding but there are still a few glitches.
Is there a better way to go about what I am trying to do? I’m pretty sure that the movement system math is used in Titanfall and it doesn’t have any problems with high-speed low lag gameplay.
PS: Anyone know why the GhostPredictionSystemGroup runs around 12-15 times every frame on clients?
@LightningDalek Hello! What quantization factor is used for your velocity, translation, rotation parameters?
You had such a difference in the accumulated delta because of resimulation, the client is always resimulate from the last received tick. Not an ideal solution but it’s all we have… usually it should be done only when an error occurs.
Of course, you can implement your own rollback system
Considering these two pieces of code if you are using Time.DeltaTime then everything should be ok… because it’s constant during ghost prediction except for last tick.
GhostPredictionSystemGroup.cs
var previousTime = Time;
var elapsedTime = previousTime.ElapsedTime;
if (simulationSystemGroup.ServerTickFraction < 1)
{
--targetTick;
elapsedTime -= simulationSystemGroup.ServerTickDeltaTime * simulationSystemGroup.ServerTickFraction;
}
for (uint i = oldestAppliedTick + 1; i != targetTick+1; ++i)
{
uint tickAge = targetTick - i;
World.SetTime(new TimeData(elapsedTime - simulationSystemGroup.ServerTickDeltaTime*tickAge, simulationSystemGroup.ServerTickDeltaTime));
PredictingTick = i;
IsFinalPredictionTick = (i == serverTick);
base.OnUpdate();
}
if (simulationSystemGroup.ServerTickFraction < 1)
{
PredictingTick = targetTick + 1;
IsFinalPredictionTick = true;
World.SetTime(new TimeData(previousTime.ElapsedTime, simulationSystemGroup.ServerTickDeltaTime *
simulationSystemGroup.ServerTickFraction));
base.OnUpdate();
}
It looks like I had two problems, first I didn’t understand the rollback system so I was trying to fix my problems in the wrong way just making my problems worse and making myself look dumb online. Second I was using my current head position to place and set the height of my character controller, adding this to the input buffer so that it can be rolled back seems to have completely fixed the problems I was having. It’s working so well in fact that I was able to turn the ping up to 270 and not notice anything different.