Hi, in this post I will be discussing Godot and how we can use our own UDP implementation to make online/multiplayer games.

Implementations using ENet

Godot comes with its own implementation of connectivity using its built-in ENet. It has a lot of good features, like sync data, RPC, and others that I didn’t use. Since it’s its own system, this means we have to use a Godot executable to act as the server or peer-to-peer implementation. Sometimes using these implementations can be a bit annoying and underwhelming.

Peer-to-Peer (ENet) — Godot

flowchart LR subgraph PeerA["Peer A (Godot)"] A1["ENetMultiplayerPeer"] A2["Game Logic"] end subgraph PeerB["Peer B (Godot)"] B1["ENetMultiplayerPeer"] B2["Game Logic"] end A1 -- ENet: connect to B IP:port --> B1 B1 -- ENet: connect to A IP:port --> A1 A2 -- send input/state --> A1 B2 -- send input/state --> B1 A1 -- receive remote state --> A2 B1 -- receive remote state --> B2 classDef peer fill:#f9f,stroke:#333,stroke-width:1px style PeerA stroke:none style PeerB stroke:none

There are a lot of functions that we can do with this implementation, like very basic games and player games where data is given and received between each other.

This implementation has many weaknesses:

  • Sometimes restricted by local networks.
    • Functionality outside of the local network becomes more difficult. For example, we don’t want the player to expose their game host across the internet to another peer. It’s possible, but not ideal.
  • All of the data will come from Peer A (the host), while the rest of the peers simply join that host.
  • For simpler games, this implementation can be a good idea, but in more complex cases there’s a different approach:
    • A wrapper service acts as the middleman, assigning peers and providing a connection between them (similar to how matchmaking or relay services work). It’s the same but it has extra steps to allow online connectivity
flowchart LR subgraph PeerA["Peer A (Godot)"] A1["ENetMultiplayerPeer"] A2["Game Logic"] end subgraph PeerB["Peer B (Godot)"] B1["ENetMultiplayerPeer"] B2["Game Logic"] end subgraph Relay["Relay Server (acts like VPN)"] R1["Forward traffic between peers"] end subgraph Wrapper["Matchmaking / API Wrapper (e.g., Steam API, lobby system)"] W1["Friend Finder / Session Manager"] end A1 -- Connect via relay --> R1 B1 -- Connect via relay --> R1 R1 -- Forward packets --> A1 R1 -- Forward packets --> B1 A2 -- send input/state --> A1 B2 -- send input/state --> B1 A1 -- receive remote state --> A2 B1 -- receive remote state --> B2 W1 -- Provides peer addresses / relay info --> A1 W1 -- Provides peer addresses / relay info --> B1 classDef peer fill:#f9f,stroke:#333,stroke-width:1px classDef relay fill:#bbf,stroke:#333,stroke-width:1px classDef wrapper fill:#cfc,stroke:#333,stroke-width:1px