Ok, wow, now I'm confused, sorry.
I don't have a function like time-to-tick.
As soon as my server is starting it also ticks and increments the local tick number every 16.6ms.
When a client is starting it is executing the following function:
public class GameLoop : MonoBehaviour {
private const float TickRate = 60f;
private const float NetRate = 1 / TickRate;
private const float SlowRate = 1 / (TickRate - 3f);
private const float FastRate = 1 / (TickRate + 3f);
private const int MinimumJitterBuffer = 2;
private float netTimer;
private float adjustedRate = NetRate;
private int addedJitterBuffer;
private int tick;
private int offset;
public void Update() {
netTimer += UnityEngine.Time.deltaTime;
while (netTimer >= adjustedRate) {
netTimer -= adjustedRate;
int lastServerTick = SteelClient.Instance.NetworkInfo.LastPacketServerTick;
float rttMillis = Client.Instance.NetworkInfo.RttMillis;
bool loss = Client.Instance.NetworkInfo.HadLoss;
AdjustTickRate(lastServerTick, loss, rttMillis);
//Note regardless of the AdjustedRate we always use a simulation deltatime of 16.6ms.
//Therefore if the AdjustedRate would be faster more simulation steps appear in a second.
tickerFunction.Invoke(systemHelper.GetTimeSinceStartup(), tick++);
Client.Instance.NetworkInfo.SetClientTick(tick);
}
}
private void AdjustTickRate(int lastKnownServerTick, bool loss, float rttMillis) {
int rttAsTick = Mathf.CeilToInt(rttMillis / NetRate * 1000f);
if(loss && addedJitterBuffer < rttAsTick + 10)
addedJitterBuffer += 2;
//The last received offset from the server. An offset of 0 means that the server received the client message associated with a tick at
//the frame it is needed.
//Note: server should always run behind the client.
offset = Client.Instance.NetworkInfo.ClientOffset;
//For a new connection server tick will be higher. Client has to snap.
if(offset < -30 || offset > 30) {
tick = lastKnownServerTick + rttAsTick + MinimumJitterBuffer + addedJitterBuffer;
adjustedRate = NetRate;
return;
}
if(offset < -2 -MinimumJitterBuffer - addedJitterBuffer) {
//The client runs to far in the future and should be dialed back a little.
adjustedRate = SlowRate;
}
else if(offset > -1 -MinimumJitterBuffer - addedJitterBuffer) {
//The client falls back behind the server and should be running faster.
adjustedRate = FastRate;
}
else {
adjustedRate = NetRate;
}
if (addedJitterBuffer > 0)
addedJitterBuffer--;
}
}
The "tickFunction" itself is basically the following:
public void TickFunction(float time, int tick) {
Client.Instance.Receive(time);
//Simulate
Client.Instance.Send(time);
}
Both, messages from my server and messages from my client have the current tick included (server messages send the server tick + the offset of the client and client messages send the tick this message should be executed at (which has to be a greater tick number than the server tick). Is that what you mean?
The minimum information my server has to send to the client (atm) is the current server tick, client to server offset and a flag if the offset was definitely too small (I can remove the flag, I know that, but I send it also if the offset is 0). The offset is simply calculated via int offset = (int) (tick - inputCollector.GetLastReceivedClientTick(id));
The overall problem I observer is that the client is not able to guarantee a delivery and my server has to duplicate input (I send at least the last three inputs my client has taken).
Again, I'm really sorry, that I can't follow you, might be an issue with me not fully understanding all the multiplayer nomenclature.
That being said, I really appreciate all the help I can get, thanks!