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)? This is a good article - http://gafferongames.com/networking-for-game-programmers/wha... If 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. I actually just noticed a bug in my code where I was only looking for data from the server every 20 milliseconds rather than every frame. Now the movement is smooth but the controls feel a bit sticky. I made the client send every 10 milliseconds and it looks pretty good, but this is a really bad way to solve this problem. I'll look at your links and try to optimize it better! Thanks a ton for those:) 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? From what I remember, the way I approached it was to have the client stepping the game world forward every frame based on whatever the current state was of all the players. 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. 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. This is all really interesting, thank you so much for sharing this with me! I just have a few questions: 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. dx is changing in response to the user making inputs. 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/
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. Local
Frame x server_message info
0 ____ no message no real idea of what the game state is
1 ____ no message
2 ____ no message
3 ____ no message
4 ____ no message
5 100 Frame=5 x=100 dx=5 we can start displaying where things are
6 105 no message
7 110 no message
8 115 no message
9 120 no message
10 125 no message
11 126 Frame=7 x=110 dx=4 (x = 110 + 4 * 4)
We ignore this message from the server as it's out of order (we've already received frame 7) 12 130 no message
13 134 Frame=6 x=105 dx=5
No need to do any stepping forward from this server state as we are in sync. 14 138 no message
15 142 Frame=15 x=142 dx=4