Netcode offline to online

Hello. I want to create game that can be played in coop using Relay service. But I also want this game to be viable in singleplayer even without internet connection. Moreover, I want to be able to switch from single mode to multi.

What I’m aiming for is something like Minecraft. Player starts singleplayer session, then, if they want, they can open this session for other players via ‘Open to LAN’ (in my case, it will be connecting to Relay).

All I was able to find is that I need two transport objects: one that is capable of creating local server without internet connection (I’m using Unity Transport) and second one, Relay Unity Transport. I start session with first one and then switch to second one when I want to open my game for others.

But that’s all I was able to come up with. I don’t know how to switch from local server to Relay and how to do so while keeping all variable values.

Does anyone of you have any idea how to do this?

1 Like

In cases like these, there is no such thing as a singleplayer game. You will only implement a server-client game with the “singleplayer” simply being the host player playing on its own, hosting a game on his local machine that will reject any incoming client connections by default (optional) via connection approval.

The functionality of “open game to LAN” is simply a switch with which the host can control whether connection approval will always reject new clients or not. With port forwarding set up, this would also allow players to join over the Internet if they have the public IP and port.

In the same way you can implement “open game to internet” and that will make the host instance connect to the Relay service, allow other clients to join and enable them to join the game over the Internet via the Relay service.

Yes, that’s exactly what I want to achieve. The problem is that I don’t know how to connect local ‘singleplayer’ server with Relay service without shutting down local server and starting new one with Relay settings.

Right now, if I just change transport layer to Relay and setup Relay data in a NetworkManager, clients will get timeout when they try to connect.

This is how I do it:

Pseudo-Singleplayer

// Set transport layer to one that allows local hosting (not Relay)
NetworkManager.Singleton.NetworkConfig.NetworkTransport = localTransport;
NetworkManager.Singleton.StartHost();

Enabling Multiplayer

// Set transport layer to Relay
NetworkManager.Singleton.NetworkConfig.NetworkTransport = relayTransport;

// Create Relay server
Allocation alloc = await RelayService.Instance.CreateAllocationAsync(15);
          
// Subscribe to connection approval method
NetworkManager.Singleton.ConnectionApprovalCallback = ApprovalCheck;
          
// Set password (host's connection also has to be approved)
NetworkManager.Singleton.NetworkConfig.ConnectionData = System.Text.Encoding.ASCII.GetBytes(passwordInput.text);
          
// Open connection and start hosting
relayTransport.SetHostRelayData(alloc.RelayServer.IpV4, (ushort)alloc.RelayServer.Port, alloc.AllocationIdBytes, alloc.Key, alloc.ConnectionData);

// Get join code, print it and copy to clipboard
string joinCode = await RelayService.Instance.GetJoinCodeAsync(alloc.AllocationId);

Ah, I see. I haven‘t used Relay yet but it makes sense that it expects the server/host session to be created via/through the Relay service. Currently there is no host migration feature in NGO and I would suspect that this also affects your use case. Though I have no first hand experience in this scenario.

Personally I would try to make the „open game“ feature to do what is necessary, ie persist the current state, end the (LAN/local) host session and start a new host via Relay. In theory this should be relatively seamless despite reloading the world on the host‘s side.

You could perhaps probe whether the Relay service is accessible, and make the singleplayer session host the game via Relay to make the transition smoother while disallowing connections until the game is opened for others. However you should test how it behaves when the singleplayer host loses internet connection. To me it seems like (for now) choosing the lesser evil, ie possible singleplayer game ending due to loss of Internet or a delay in moving the currently running game to an online state.

All the while check if NGO starts supporting host migration. Check the roadmap, if host migration isn‘t on the roadmap you may want to request it, otherwise vote for it.