Netcode for GameObjects (Netcode) allows you to connect to a host by its IP and port. However, if the host is not on the same network as you (i.e. somewhere over the Internet), you will need some extra services to achieve a successful connection and thus a successful game.
Many factors impact how you connect to the remote host, and it can be tricky to implement. There are two ways of achieving such a connection:
- NAT punching: an advanced technique that allows you to directly connect to the host computer even if it is on another network.
- Usage of a Relay server: the server is on the Internet with a public-facing IP that you and the host can reach. After the connection to the Relay, it will pass along the messages to all the other party members connected.
Netcode does not offer tools to help you do a successful punch through a NAT. But, Unity Services provides a Relay Service that can relay all Unity Transport based technology, like Netcode.
You need to install the Unity Relay SDK if you want to interact with the service. To install it, add
com.unity.services.relay package to your project.
The host of your game needs to allocate a Relay first. This process will create the Relay server and allow the clients to connect to it. Once done, you will be able to get a join code from your server. It is a random string that your clients will provide to the SDK to join the correct server.
The first thing that needs to be understood is that Relay is a Unity service. Thus, you need to add it to your organization in the Unity Dashboard (under the multiplayer section). After that, link your project to your organization (Project Settings -> Services).
To allocate a Relay server, you need to make an authenticated call to Unity backend using their SDK. Call the
CreateAllocationAsync method with the maximum number of users your Relay will handle. This function can throw exceptions, and catching them can give you hints about the underlying error.
Allocation class represents all the necessary data for a Host player to start hosting using the specific Relay server allocated. You don't need to understand each part of this allocation. You will feed them to your chosen transport that will handle the relay communication on its own. For the more curious and for reference, here is a simple overview of those parameters :
RelayServerclass containing the IP and port of your allocated server
- The allocation ID in a Base64 form and GUID form referred to as
AllocationIDA blob of encrypted bytes representing the connection data (known as
ConnectionData) allows users to connect to this host.
- A Base64 encoded
Keyfor message signature.
Each allocation created a unique join code which is a simple string. This join code will allow your clients to join your game. You can retrieve it by calling the Relay SDK like so :
With those two calls, you now have your Relay server ready and the associated join code. Pass the allocation parameters to your host transport and send the join code (a simple string) over the Internet by the mean of your choice to your clients. Finally, remember always to authenticate your users before using SDK methods. The easiest way is the anonymous one (shown in the following code snippet), but you can use more advanced techniques.
To sum up, here comes the whole code that allows working with the Relay server.
The host of your game allocated the Relay server, and your client has received its join code. You now need to request all the allocation parameters from the join code to join the game. To do that, call the
JoinAllocationAsync method with your join code like so :
JoinAllocation type is similar to the
Allocation one used before with the host. This type adds a blob of bytes which is the
HostConnectionData that you will need to give to the transport of your choice so you can connect. Finally, like for the hosting part, always remember to authenticate your user beforehand. Here is the code often used to join a Relay :
Now that you have an allocation (either by joining or hosting), you need to make all traffic coming from Netcode go through the Relay. And to achieve that, you need to pass allocation parameters to your transport. For now, only the
UnityTransport supports the Relay protocol. To pass allocation parameters to it, you first need to retrieve it from your
NetworkManager like so :
You can now call the method
SetRelayServerData on the retrieved transport with all the allocation parameters in this order :
- The relay server IP address, found in the
RelayServerproperty of the allocation
- The relay server port, found in the
RelayServerproperty of the allocation
- The allocation ID in Base64 encoded bytes.
- The key in Base64 encoded bytes.
- The connection data in your allocation
- If you are joining a game: the host connection data retrieved during your call to join. Make special attention since the host connection data is an optional parameter but must be pass in case of join.
Your transport is now correctly configured. You can call
StartHost and use the Netcode library as usual.
For more information see Unity Relay