I’m trying to set up a lobby system for a unity game and it mostly works.
But i have run into an issue where for some reason the lobbies are not working for a build connecting to a build but it works with the editor connecting to the build or the build connecting to the editor.
I have no idea why this is happening.
This is the lobby code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading.Tasks;
using Unity.Netcode;
using Unity.Netcode.Transports.UTP;
using Unity.Services.Authentication;
using Unity.Services.Core;
using Unity.Services.Lobbies;
using Unity.Services.Lobbies.Models;
using Unity.Services.Relay;
using Unity.Services.Relay.Models;
using UnityEngine.UI;
using TMPro;
using System;
public class SimpleLobby : MonoBehaviour
{
private Lobby _connectedLobby;
private QueryResponse _lobbies;
private UnityTransport _transport;
private const string JoinCodeKey = “j”;
public string playerName;
private string _playerId;
private string lobbyCode;
[SerializeField] private TextMeshProUGUI lobbyCodeText;
[SerializeField] private Button playButton;
[SerializeField] private TMP_InputField nameInputField;
[SerializeField] private TMP_InputField codeInputField;
[SerializeField] private GameObject lobbyUI;
private void Awake() => _transport = FindObjectOfType();
public async void CreateOrJoinLobby()
{
playerName = nameInputField.text;
await Authenticate(playerName);
_connectedLobby = await QuickJoinLobby() ?? await CreateLobby();
if (_connectedLobby != null) lobbyUI.SetActive(false);
}
public async void JoinByCode()
{
playerName = nameInputField.text;
await Authenticate(playerName);
_connectedLobby = await GetLobbyByCode();
if (_connectedLobby != null) lobbyUI.SetActive(false);
}
private async Task GetLobbyByCode()
{
try
{
// Attempt to join a lobby in progress
var lobby = await Lobbies.Instance.JoinLobbyByCodeAsync(codeInputField.text);
// If we found one, grab the relay allocation details
var a = await RelayService.Instance.JoinAllocationAsync(lobby.Data[JoinCodeKey].Value);
// Set the details to the transform
SetTransformAsClient(a);
// Join the game room as a client
NetworkManager.Singleton.StartClient();
return lobby;
}
catch (LobbyServiceException e)
{
Debug.Log($“No lobbies available via quick join”);
return null;
}
}
public async Task Authenticate(string playerName)
{
//this.playerName = playerName;
InitializationOptions initializationOptions = new InitializationOptions();
initializationOptions.SetProfile(playerName);
await UnityServices.InitializeAsync(initializationOptions);
AuthenticationService.Instance.SignedIn += () =>
{
_playerId = AuthenticationService.Instance.PlayerId;
Debug.Log("Signed in " + AuthenticationService.Instance.PlayerId);
};
}
private async Task QuickJoinLobby()
{
try
{
// Attempt to join a lobby in progress
var lobby = await Lobbies.Instance.QuickJoinLobbyAsync();
// If we found one, grab the relay allocation details
var a = await RelayService.Instance.JoinAllocationAsync(lobby.Data[JoinCodeKey].Value);
// Set the details to the transform
SetTransformAsClient(a);
// Join the game room as a client
NetworkManager.Singleton.StartClient();
return lobby;
}
catch(LobbyServiceException e)
{
Debug.Log($“No lobbies available via quick join”);
return null;
}
}
private async Task CreateLobby()
{
try
{
const int maxPlayers = 10;
// Create a relay allocation and generate a join code to share with the lobby
var a = await RelayService.Instance.CreateAllocationAsync(maxPlayers);
var joinCode = await RelayService.Instance.GetJoinCodeAsync(a.AllocationId);
lobbyCode = joinCode;
lobbyCodeText.text = "Server code: " + joinCode;
// Create a lobby, adding the relay join code to the lobby data
var options = new CreateLobbyOptions
{
Data = new Dictionary<string, DataObject> { { JoinCodeKey, new DataObject(DataObject.VisibilityOptions.Public, joinCode) } }
};
var lobby = await Lobbies.Instance.CreateLobbyAsync(“Useless Lobby Name”, maxPlayers, options);
// Send a heartbeat every 15 seconds to keep the room alive
StartCoroutine(HeartbeatLobby(lobby.Id, 15));
// Set the game room to use the relay allocation
_transport.SetHostRelayData(a.RelayServer.IpV4, (ushort)a.RelayServer.Port, a.AllocationIdBytes, a.Key, a.ConnectionData);
// Start the game. i’m doing this immediately, but maybe you want to wait for the lobby to fill up
NetworkManager.Singleton.StartHost();
return lobby;
}
catch(Exception e)
{
Debug.LogFormat("Failed creating a lobby " + e);
return null;
}
}
private void SetTransformAsClient(JoinAllocation a)
{
_transport.SetClientRelayData(a.RelayServer.IpV4, (ushort)a.RelayServer.Port, a.AllocationIdBytes, a.Key, a.ConnectionData, a.HostConnectionData);
}
private static IEnumerator HeartbeatLobby(string lobbyId, float waitTimeSeconds)
{
var delay = new WaitForSecondsRealtime(waitTimeSeconds);
while (true)
{
Lobbies.Instance.SendHeartbeatPingAsync(lobbyId);
yield return delay;
}
}
private void OnDestroy()
{
try
{
StopAllCoroutines();
// todo: Add a check to see if you’re host
if(_connectedLobby != null)
{
if (_connectedLobby.HostId == _playerId) Lobbies.Instance.DeleteLobbyAsync(_connectedLobby.Id);
else Lobbies.Instance.RemovePlayerAsync(_connectedLobby.Id, _playerId);
}
}
catch (LobbyServiceException e)
{
Debug.Log($“Error shutting down lobby: {e}”);
}
}
}