In this lesson, you will learn how to leverage the Unity Relay service to bypass NAT restrictions and enable direct peer-to-peer connectivity for your multiplayer sessions.
The NAT Problem
Most home routers use Network Address Translation (NAT), which prevents external devices from initiating a connection to a computer inside a private network. In a typical client-server setup, the "host" player is usually behind such a firewall, making them unreachable to other players. Unity Relay solves this by acting as a secure "middleman" that routes traffic between players, allowing them to communicate without requiring complex port forwarding or manual router configuration.
Provisioning the Allocation
To establish this connection, the host player must first request an Allocation from the Relay service. This allocation acts as a virtual meeting point. Once the host receives the allocation, they obtain a JoinCode—a unique string identifier that the host shares with friends.
When other players (clients) input this JoinCode, the Relay service uses it to identify the specific allocation and route their packets directly to the host. Because both the host and client are communicating with the Relay server—which is publicly accessible—the NAT constraints are effectively neutralized.
Implementing the Connection
In your NetworkManager logic, you perform this provisioning using the RelayService SDK. Here is the core flow:
// Host-side: Create the allocation and get a join code
Allocation allocation = await RelayService.Instance.CreateAllocationAsync(maxConnections);
string joinCode = await RelayService.Instance.GetJoinCodeAsync(allocation.AllocationId);
// Update your NetworkTransport to use the Relay server data
var relayServerData = new RelayServerData(allocation, "dtls");
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(relayServerData);
NetworkManager.Singleton.StartHost();
By passing the RelayServerData to the UnityTransport component, you instruct the NetworkManager to send all traffic through the Relay instead of attempting a direct IP-to-IP connection. Clients perform a mirror process using JoinAllocationAsync(joinCode) to synchronize their transport settings with the host’s allocation.
Key Takeaway: Unity Relay dynamically creates a public-facing virtual endpoint that allows players behind restrictive NATs to act as hosts, ensuring reliable connectivity regardless of their network hardware.