Me again.
I’m using an external simulator (clumsy.exe) to simulate really bad networking with 10% chance for packet loss under Windows.
What happened is that I got strange jerks in my movement although I had checked all my prediction and correction code with the old networking.
So I went debugging to see where my script goes wrong and I ended up at the command sending from client to server.
As I need a periodic snaphot with fixed update rate I issue a Command on the client every fixed update loop. I’m aware this is expensive, but I need it that way for having framerate independent, reproducable data snapshots.
The server would not have a problem with delay due to high latency and poor networking, but there must be no lost package.
I added some debug code and found out, if I simulate packet loss, I receive the packages in disorder. I added a SortedList buffer to fix this. However I also seem to completely lose some of my snapshots sent via Command Call and my SortedList would go crazy forever as the late package never arrived.
Now I’m wondering if commands even are full 100% reliable.
Am I missing something here?
Thank you for help.
My problem I will solve by allowing a snapshot drop, if my SortedList buffer exceeds a certain size, but still I wonder what is happening.
Debug Code:
//server code
private Queue<NetKeyState> pendingInputs;
private SortedList<int, NetKeyState> postponedInputs;
public int nextId = 1; //when stuck, will show the id which was never transferred
public int postponed = 0; //watch in editor and see the SortedList exploding after a while
public void UpdateClientMotion(int id, int inputData)
{
NetKeyState keyState = new NetKeyState(id, inputData);
postponed=postponedInputs.Count;
if (id == nextId)
{
//correct order, add to queue
pendingInputs.Enqueue(keyState);
nextId++;
//grab any postponed followup keystates
while(postponedInputs.ContainsKey(nextId))
{
pendingInputs.Enqueue(postponedInputs[nextId]);
Debug.Log("enqueue "+nextId);
postponedInputs.Remove(nextId);
nextId++;
}
}
else
{
Debug.Log("postpone " + id);
//wrong order, put aside
postponedInputs.Add(id, keyState);
}
}
//server side
//issue command in "client" behaviour and on server side call function in "server" behaviour.
[Command(channel=0)]
private void CmdUpdateMotion(int messageId, int data)
{
//running on server
if (isServer)
{
svManager.UpdateClientMotion (messageId, data);
}
}
//client side
//stripped down version
void FixedUpdate ()
{
if (isLocalPlayer)
{
messageId++;
//send key state to server
if (connectionToServer.isReady)
{
//at this point no message is being missed yet
Debug.Log(messageId);
CmdUpdateMotion(messageId, data);
}
}
}