Godot Multiplayer: 3 Quick Tips for Better Netcode

Gamedev is hard. Networking is even harder. Luckily, I'm here to make your life easier by sharing some quick tips I picked up for creating networked multiplayer games in Godot.

1.Let the server handle it.

Game dev is hard, and multiplayer makes it even harder. Multiplayer games involve multiple instances of your game. Each of those instances have many objects that can move or change. Those updates need to be shared with each other instance to maintain a consistent world.

The source of many bugs & challenges in multiplayer code boils down to "who's the authority?" The authority is the instance of the game that has the final say about any changes.

Let's look at a barrel. If a barrel moves in 1 game, we want it to move in another game.

be updated and syncronized to maintain a consistent shared world.

This is where authority comes in.

The authority of a networked object has the ultimate power to make definitive decisions about that object. Each object must have one and only one authority. The authority has the final control over all state and behavior of that object.

2. Server authoratative is not optional

Many people shy away from creating a fully server authoratative game. "But what about muh P2P?" is a common question. That's NOT what I'm talking about.

Having a server be the authority is not optional because someone has to have the final say on who gets to do what. That means you ALWAYS have a server, even if that server is on a peer machine, with a player.

3. Dedicated Server is easier (yes, even for P2P)

I have gone full server authorattive, and to that end, I also recommend the dedicated server appraoch from day 1. That absolutely does not mean you can not do P2P, you totally can.

What it means is that your sever will be rock-solid & able to handle all changes and broadcast them to all players & clients, no matter where they are.

The benefit is that you will have 1 place all the changes are taking place, and it's very flexible then to take that & run it alongside a P2P host. Yes, that's a little more resource intensive, as you have

But if you follow all my instructions above about --headless & turning of processing on the clients, you will hopefully be in a good spot.

Disclaimer: None of this is aimed at triple AAA or hyper competitive multiplayer games. If that is your market, you likely didn't get this far in the blog.

In games, there are two kinds of authority strategies:

  1. Server Authority
  2. Distributed Authority

In the server authrorative model the server has the final say. The server decides what happens, and is responsible for informing each client what hapened, usually sending information about position & visual state of the objects to the clients.

In the Distributed Authority model, the server owns many of the objects, but some may be controlled by the client.

It's useful to send as little as possible

Let's talk about authority in games. Authority is the concept of where definitive decisions about networked Objects happen

There are two main methods of

https://www.youtube.com/watch?v=sT0UPlJ2cpc

the server is exclusively responsible for maintaining the game state. The server then shares only what is strictly necessary to clients. Usually that's restricted to information required to render the world visually.

The reason why server authoratitve code works best is that if both the server & client share the responsibilty of updating state & handling logic, the source truth becomes multiplied as well as the source of bugs. It's hard to decide who controls what & tracking down differences becomes tough.

I have found it best to do as little as possible on the client, even going so far as to disable processing and turn off collision detection (like with ray casts).

func _ready():
    if not multiplayer.is_server():
        return

func _process():
    if not multiplayer.is_server():
        return

This often saves frames & can increase client performance. I also find that if you start with a server authorative approach, and it works on the server, it's going to work for all clients. Again the issue with sharing responsbility is that if you change things on the client, you have to inform not only the server about the change, but other clients as well!

2. Use a Dedicated server.

--headless

3. Projectiles in Multiplayer: You might not need a MultiplayerSyncronizer!

Spawning and tracking projectiles is usually done with a MultiplayerSpawner and a MultiplayerSyncronizer.

A player fires a weapon (usually as an RPC, or )

But there's another, very fancy and

2. Use .rpc_id for static content

Continuing with the theme of "you might not need a multiplayer syncronizer", let's look at a common example.

3. OnChange ?

Server Authorattive

Godot's built-ins are great & MultiplayerSyncronizer is no different, but it's quite heavy. Great for starting out, but after enough time you find ways.

Sources: