Reliability of Commands

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);
            }
        }
    }

Hey Fireball,

I don’t have the time at the moment to read your code (just heading out the door) but I’ve been working on the same problem of client-side prediction and server reconciliation, and I ran into a similar issue. My guess at what’s happening is that as Commands are reliable (I’m assuming! Since it would be ridiculous to lose a method call), when the packet times out the client re-sends the data, causing it to arrive after packets that were sent out earlier.

Anyways, my solution was to switch to using SendUnreliable, which not only allows you to send a specific message type of unreliable data, but also to send data from objects that are not localPlayerAuthority (which is nice if you want your characters to drive cars or whatever)

Command QOS can be setup at will using the [Command(Channel=x] attribute, however it seems that some internal message buffer will just give up at a certain point (too many packages lost so there is no way to catch up again).
There are other QOStypes defined for both reliable and unreliable, but I have yet to find out how to get them work with a NetworkBehaviour besides the default channels.

Allowing to have snapshot drops with really bad networking appears to be working well enough.

Hopefully nobody tries to play a game in such a lossy network as I use for stability testing… :smile:

I have been working on a Web Player game which is abetting game.
In this there are 10 objects and all run at different speed and animation clips are applied on it as well but the game does not play or run smoother it takes jerks so how do I remove this problem from my project?

Please anyone knows then kindly help me out…!
Thanks

This is a bit off-topic, but do you have considered sending the updates not on every fixed update step but instead let’s say every N fixed update step? (for example using a counter)

I did, but this causes artificial lag as the server will always get some “frames” late and thus cannot provide updated position data to send back to all clients. So I dropped that again. With old networking it was around 1kB/s upstream for each client. Expensive, but still doable.

1 Like

Ah alright, I see, thanks for the info.