This new system makes vehicle -> vehicle collisions possible, as well as physics on NPCs & player controlled characters. Real-time networked object physics will now be possible for the streetside objects as well.
Network bandwidth usage has been cut to < 7kb downstream each second which is a lot less than it was before, and the bandwidth required to upload the changes in the user's input is trivial, < 0.1kb a second. Frame rates should be a lot higher now on slower computers, since a lot of calculations have been moved to the server.
I had some reservations about getting this to work, but I am pleasantly suprised with the results so far. Some quick points of interest regarding the multiplayer physics -
- Physics calculations are done server side @ 150FPS [using the Newton Physics Library].
- Game update packets are send to clients 15-20 times a second. Actors, Vehicles, Objects are each sent in different packets, one per frame, containing all the changed information for that type of object.
- Take each 3x3 rotation matrix and convert it to a quaternion before sending across the network, saving you 5 floats per object.
- Have a tight ring around client characters which turns off physics for distant objects.
- Do an initial sweep of all physics objects...flagging each as 'needing to be sent', by comparing to the value last sent to that client.
- Save 'last sent' values for each client, don't just set the last sent values after each update.
- Break up vectors & quaternions into separate elements (ie: w,x,y,z) checking to see if each element has changed, and only sending the changed element verses the entire vector/quaternion.
- Use a 'delta value' to reduce frequency of sending values across the network...some pseudo code..
//Sync a quaternion element the easy way...if(Quaternion.w != LastSentQuaternion.w) { Send(Quaternion.w); LastSentQuaternion.w = Quaternion.w;}...//Now the better way...use a delta value to reduce bandwidth.//Higher delta values reduce bandwidth, lower values produce better results, but use more bandwidth.float QuaternionDelta = 0.001;if(fabs(Quaternion.w - LastSentQuaternion.w) > QuaternionDelta){ Send(Quaternion.w); LastSentQuaternion.w = Quaternion.w;}
By using 0.00001 as my delta value [for rotations and positions] things looked like they were local. In practice 0.001 tends to be a good balance...while 0.01 looked way too choppy.
I've also coded up a net-graph to help debug the networking. All packets received during a frame are displayed on a single line, each packet type is color coded. I display the last 150 frames in the netgraph.
In my tests on the server (with 2 clients and 30ms-50ms ping) the vehicle + actor physics synchronization worked flawlessly...being able to truly interact with other people online will add so much to the game. I must admit I based the system off the networking in the Source engine...I've implemented almost everything in this article [ Source Engine Multiplayer Networking. ] except for the client side prediction, which will come later, after I can get a better feel for the lag levels.
I will probably post a video in the next few days [grin]. I'm extremely excited with how good things are working out with the new netcode though...except it's going to take a day or two longer than I had hoped.
- Dan
User hits key -> client sends command to server -> Server calculates move -> New position is sent to user -> User rerenders
Seems like it'd get frustrating as lag increases.