Help with server logic for a multiplayer game server in GO/Unity
I am trying to create a simple multiplayer server for a simple game using GO. I currently have it so that users can join, sign in, connect, and see other users. The issue I currently have is that moving around is very laggy because I send user input to the server and all actions are performed on the server rather than on the client. Clients and the server only get and send packets every 20 milliseconds.
I was wondering what the best solution to this is. I feel like I have 2 options: exchange a lot more packets to make the game run a lot smoother for the client, or create some sort of prediction on the client where the client will do what it thinks is right until corrected by the server.
I read somewhere that Agar does not use any client side prediction/correction so it must be possible to continue without that.
What is the down side to sending more packets? Is that a reasonable way to solve this lag issue? And if so should I only send more on one side of the game to be optimized correctly (as in send a lot of packets from the server but not a lot from the client)?
5 comments
[ 2.8 ms ] story [ 14.8 ms ] threadIf you really are sending packets every 20ms then that is the equivalent of 50fps - I suspect that if you log out how often you are getting packets from the server you'll find that you are not actually getting packets at that rate, or the jitter on the packets is unacceptable.
Client side prediction doesn't have to be very clever. You can get good results with very simple algorithms.
I gave a talk on this a few years ago at iOSDevUK - https://dl.dropboxusercontent.com/u/508075/GameCenter%20and%...
I'm not an expert in games, but even my simple code worked pretty well.
From what I remember I was sending user inputs from the client side every 0.2 seconds - and from the server once I had the client prediction in place I could get away with very slow updates from the server and still have the illusion of 60fps.
Edit: I read your keynote and I'm not sure how exactly your client prediction worked. Is there any video anywhere of the keynote? Or could you give a brief description?
So for example if a player is going left, every time the game steps forward one frame move the player left.
Then when a message comes from the server with the current game state, update everything to the server positions and then step your game world forward to now.
So a simplified example - we have one object in our game that has an x position and a delta x to move it.
So we set our local state to what the server says and then step forward by 4 frames to get what we think the current state should be. We ignore this message from the server as it's out of order (we've already received frame 7) No need to do any stepping forward from this server state as we are in sync.One thing to be careful of is that normally it's not just a case of saying it's 4 frames so I just multiply everything by 4 to get the new positions. With physics engines and more complete calculations you probably want to step the world forward frame by frame to get a better simulation of where everything is.
Hope that all makes sense.
Wouldn't the numbers for the current frame get really huge as the game progresses?
How would this method of sending the current frame (from the server) and matching it with the client work if there were a lot of people on the server? Would the server have to keep track of the current frame of each player?
Why does dx change? Are we not assuming in this example that the character is moving right at a consistent speed?
I am using TCP, I shouldn't have to worry too much about packets coming in incorrect orders right? But it's probably still good to implement your method of dealing with it just in case.
Imagine you are showing a different players character - at first the server tells us he is moving to the right by 5 pixels per frame. So we start moving him, in the absence of any more information we keep moving him, then we get a message from the server saying 'actually several frames a go the player decided to move at 4pixels per frame' we have rewind our predictions back to the when that happened and then replay with the new movement speed.
For the current frame I just took the first packet received from the server as the baseline frame.
So if you get a packet from the server saying "the game is currently at frame 100" that's your baseline frame, start counting from there.
You're right, if you're using TCP then you don't need to worry about out of order frames.
One of the issues with TCP is that if you are going over a slow connection to some players they will get behind the gameplay. With UDP packets if they are on a slow connection the packets will just be thrown away and they should keep up with the latest game state.
If you do a search "udp vs tcp games" you'll find a whole host of discussions.
e.g. http://gafferongames.com/networking-for-game-programmers/udp...
Personally I prefer udp - but then you have to be careful about packet sizes.
This is a pretty good library that lets you mostly forget about udp or tcp - http://enet.bespin.org/