Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
Tags

Kiffen & Maintane

An online multiplayer platformer about building a cute home by a lake (and dying to a spike 20 times). · By socks and hair, ren ren

Making Online Multiplayer Actually Work: Analysis of GDevelop P2P Programming Sticky

A topic by socks and hair created Feb 26, 2022 Views: 231
Viewing posts 1 to 1
Developer (1 edit)

I usually never use caps lock (it's funny writing styles exis dee) but for the sake of legibility, I will right now.

I am the programmer for this game, and I learnt a lot from working on the online multiplayer aspect of it. I have worked with online multiplayer in the past using GDevelop's peer to peer options, but never got past small, barely functional prototypes.

Here's what I've found!

How does it even work???

It is both easier and harder than you'd imagine.

Think of it as a text message in a group chat. When you write the message, the message may be stored on your end in text before you send it, but it won't be sent yet so nobody else can see it. That data is stuck with you, the client, and you control what happens to it. However, if you do send the message, then that data will be sent to other people in the group chat. It wouldn't just be on your client but everybody else.

That is essentially how it works with online multiplayer through peer to peer connections. You take action in your client, that data gets sent to other people, and those clients take action based on what they receive. And of course, you can choose to have some data not be sent at all and keep it with the individual client.

In this case, say Kiffen (the blonde player) jumps. The client would send that they, Kiffen, jumped to other clients. Those clients would then tell Kiffen to jump once receiving the event. That's pretty simple and straightforwards.

The Catch: Latency

But it's not all straightforwards, because lag exists. Latency exists.

When you send the message on your phone, there may be a slight delay before other people get it. The same applies for emails when you get a verification code sent to your inbox, and the same happens here with the actual video game.

When the client controlling Kiffen jumps, they appear to jump. When the client controlling Maintane jumps, she appears to jump. But if there is any delay, then Kiffen may appear to jump at a different timing than Maintane, and Maintane may appear to jump at a different timing than Kiffen. 

That's to be expected, each player could be in a different building, or town/city, or county, or state, or country, or even continent. So... what can you do to help adjust? If lag is a guarantee, how do you keep everything having client parity?

Well... correctional code, or accommodating for the inevitable.

Correctional Code

For example, when Kiffen jumps, the jump may be triggered slightly behind on Maintane's end, but if Kiffen jumps and runs, there may be a chance that the timing between each event is different for Maintane. Maintane will just see that her friend jumped and ran into a wall instead of jumping over a wall. Meanwhile, Kiffen will be just standing happily at the other side of the wall, and if they choose to run forwards more, they can continue and do more things. Except... for Maintane, Kiffen will appear to be still running into that same wall they never jumped over.

To fix this, having code to send Kiffen's exact coordinates after a set interval and force Kiffen to appear in that position on Maintane's end will do one of two things:

  • nothing because the clients are synced so Kiffen is in the proper place each time (in the best case scenario with good connectivity)
  • ensure Kiffen is closer to where they actually are each time (ex. instead of still running into a wall, Kiffen may teleport behind the wall at the right position. It may break immersion a little, but so is Kiffen running into a wall for 2 minutes instead of being behind and past it)

This correctional code fixes the biggest problem (sometimes): the players being so out of sync at times that they are completely far from where they are supposed to. But I say sometimes, because sometimes lag will be where it is so bad that each player is way too delayed for the game to handle. Because if the game delays inputs, what prevents it from delaying position corrections? There just will always be cases like this at some point with peer to peer connections and you have to be able to accept not everybody will be able to get the perfect experience. You just need to find a balance and spot to be happy with.

Accommodations for the Inevitable

Here's an example.

Enemies exist in the game. How do they sync with each player? You can choose for one player to act for it, where enemies move normally for them and enemy movement is sent to other clients. But... what about lag? That can lead to enemies teleporting and unfairly killing players.

For this, a solution (and the one this game takes) is having enemies be only player-side, aside from when enemies die. That means all players will always have their enemies where they see them which prevents unfair deaths, but... what about the fact the enemies may be off sync for others? The enemy could be on the right for Kiffen but on the left for Maintane.

This is the compromise and accommodation. Leaving the players not synced aside from when they are brutally jumped on to death is always going to have its own flaw of enemies possibly being in different positions for other players, but it stops a bigger issue of unfair dying. And this is what has to be done for a smooth multiplayer experience. You have to be willing to let some parts not be as perfect with peer to peer, because each client is connecting to each other to make it even work and they are not relying on a big server somewhere that controls everything.

Other Interesting Notes

I guess that takes care of the big stuff, so let's get into various stuff I learned.

  • Have checks for what player is what whenever you can! Each client for this game stores what player number they are to properly check if input happened and what player they were so they can move the player accordinglyThese checks will come up a lot, so if you step back and think "man this code is cluttered with checking every time what player you are," yeah, it happens.
  • Take advantage of a host vs joining client. The host can let you designate one place for authority over some issues which may happen and need a singular player to make a decision. 
  • Keep in mind what to display for each player. In this game, some sound effects only play for specific players when they do things. This includes killing an enemy, because if a different player kills the enemy, that sound effect may happen when others are nowhere near the dead enemy. This is just an example of making sure to know what data to send and what not to send.
  • Open two previews of the game at once when testing and have them join each other. Yes, you can do that. Yes, I didn't realize that until this project and I've been using GDevelop since GDevelop 4 with years of experience. It took a bit for me to figure this out instead of purely making a debug mode (that became the single player mode. not that making a debug mode is bad, it just makes some issues harder to test before compiling).

So... what else?

There's honestly not much else to say.

Just always remember: no matter what you do, online multiplayer is impossible to make a perfect experience. But if you do what you can to ensure the smoothest possible experience knowing some issues will occur and prepare your game for the event of that happening, then things can be hopefully successful!

I hope this was helpful in understanding some aspects of peer to peer connections. I think most of what I said applies to the majority of game engines with peer to peer multiplayer support, so hey, if you are using multiple game engines for different projects like me, this might be beneficial for you!

If you also are new to peer to peer with GDevelop, I recommend looking up "The Gem Dev GDevelop Multiplayer" on YouTube for a good and detailed guide on getting it setup.

This game jam has been fun, and I'm very proud of what Maren (me + ren who is the artist and epic like a boss) has made. Good luck to everybody and have a good one!