Basically we're trying to synch the client and server so that they both represent the position of an object at the same place. when the server updates the world and finds that an object has moved, it will send that information to the client-- its important that that position is not much different than what the client currently has or object will apear to jump or 'teleport' when updated with the correct position value.
First lets start with what data is being dealt with on the client and on the server:
Client has:
Entity ( position, facing, velocity )
Server has:
Entity ( position, facing, velocity )
On Update, the client and server BOTH to the following to their entity:
Code: Select all
Entity.pos += Entity.facing.normalize() * Entity.velocity * (float)(timeSinceLastUpdate/1000.0f);
Instead, we add a part of the velocity according to how much time has passed. This means that if the client updates 40x/sec and the server updates 30x/sec, they will still move the Entity by the same amount.
So far so good?
Now the trouble starts when the client wants to tell the server to move one of the Entities. The biggest trouble is the difference in time between when the user pushes a 'movement' button on the client, and when the server recieves that command.
Lets go over a simple brute-force way first: the client will send a packet to the server saying it wants to set the velocity(and/or)facing of Entity to something new. The server will store this SEPERATELY from the Entity's current velocity(and/or)facing. Then on update, the server will run this code instead:
Code: Select all
Entity.pos += Entity.facing.normalize() * Entity.velocity * (float)(timeSinceLastUpdate/1000.0f);
Entity.velocity = newUserVelocity;
Entity.facing = newUserFacing;
![Image](http://www.technomagicum.net/projects/networkUpdates.gif)
In the above image I show 2 ways of doing things. Green lines represent the Entity velocity and position on the client and server across multiple world updates. The red circles represent user input, and the black arrows show the lag time it takes to get from the client to the server. Note, the first user input is created and applied during the SAME world update, but its possible (as in the second case) that user input is created and not recieved by the server until one or even MORE world updates later.
In the above image the TOP row shows what happens when we apply the user input to the entity AFTER the world update (all of the green lines are synched up nicely). The BOTTOM shows what happens when we apply the user input BEFORE the update. In the bottom one we see that the entity position/velocity gets out of synch during world update 0 and during world update 2. This will result in a jump of the enity on the client side when it recieves world updates 1 and 3. Thats why we want to hold off on applying the user input until after the world update we recieve it in.
This example assumes that the client and the server run world updates at the same frequency (since the world update 'bars' are the same on client and server).
Furthermore, there is still the problem of lag time between when the user pressed the movement key, when the server recieved it and when the client then displayed that new position.
What we'd like to see is for the client to start applying the result of the user input as soon as it happens, assuming that the server will return the next world update with that movement already taken into account. Thats what I'm currently working on.
![Embarassed :oops:](./images/smilies/icon_redface.gif)