Advices on multiplayer implementation

I am developing a top down shooter and my singleplayer is pratically finished so now I want to move on to develop multiplayer but I have some questions and I am seeking for some advices.

In my game a match is constituted by a character(two in a multiplayer match) , monsters, projectiles, boosts and spawn points.

Here is my initial solution:

Characters- Send to the game server my character(position, if it´s dead or not,currentHealth,etc) and receive the other player character from the server. Thinking about using UDP because I want real time positions

Monsters- My strategy for this one is having the server randomly choosing one of players´computer to handle the spawn of the monsters .The list of monsters is sent to the server and the other player gets it. Thinking about using TCP because a lost package would imply that the round will have less monsters than it should have

Projectiles- When a player clicks the left button to shoot a projectile, the input is sent to the server. This means that the projectiles list would be instanciated in the server and both players will have to get it from it. 99% sure I will use UDP because a lost projectile wouldn´t have a major impact on the match.

Boosts- Probably the same strategy as the monsters. Pretty sure I will be using TCP because if the boost doesn´t spawn in that round it completely alters the match.

I am looking for critics to the strategies I am planning to implement as well as some advices

Characters- Send to the game server my character(position, if it´s dead or not,currentHealth,etc) and receive the other player character from the server. Thinking about using UDP because I want real time positions

Yes. Also for an action game like this you’ll probably end up sending things like the players inputs or at least velocity, for some client-side prediction.

Monsters- My strategy for this one is having the server randomly choosing one of players´computer to handle the spawn of the monsters .The list of monsters is sent to the server and the other player gets it. Thinking about using TCP because a lost package would imply that the round will have less monsters than it should have

That would be pretty weird to do. You should get a udp system that supports sending reliable and ordered packets alongside normal unordered ones.

Another approach I am thinking following is to share a random seed between the two players. This way both players would spawn the same enemies

So instead of sending the current position of a character should I send if the player pressed A,S,W,D to

Welcome to desyncville, population: your game.

Imagine for a moment there was a half second lag spike, you’ve seen it playing online games before I’m sure.

The client then receives the UDP packets out of order, as is allowed under the UDP protocol. They get the “move bullet ID 173 here {x,y}” message before they get the “spawn bullet ID 173 at {x,y}” message.

What do you do with this information? Ignore it because you don’t have a bullet 173? Hold onto it until you can use it? What if you never get the spawn bullet 173 message, that’s allowed by UDP too. UDP is powerful and performative, but state management is not as easy as you might think.

God help you if you try and use a RNG(same seed or not), even with TCP that’s a pit trap designed to swallow young networking developers whole.

I would recommend a 3rd party UDP library, the lidgren network:

There are five delivery methods available:

  • Unreliable This is just UDP. Messages can be lost or received more than once. Messages may not be received in the same order as they were sent.
  • UnreliableSequenced Using this delivery method messages can still be lost; but you’re protected against duplicated messages. If a message arrives late; that is, if a message sent after this one has already been received - it will be dropped. This means you will never receive “older” data than what you already have received.
  • ReliableUnordered This delivery method ensures that every message sent will be eventually received. It does not however guarantee what order they will be received in; late messages may be delivered before newer ones.
  • ReliableSequenced This delivery method is similar to UnreliableSequenced; except that it guarantees that SOME messages will be received - if you only send one message - it will be received. If you sent two messages quickly, and they get reordered in transit, only the newest message will be received - but at least ONE of them will be received.
  • ReliableOrdered This delivery method guarantees that messages will always be received in the exact order they were sent.

Simply if you work with data that is negligible, e.g. XY coordinate data in each frame, you can use the Unreliable function, and if you generate / remove something or any other important data update, you can definitely use ReliableOrdered.
Of course, I definitely recommend the server-client approach, much simpler.

1 Like