Hello,
I am working in Unity 2021.3.19f1, NGO 1.2.0, Lobby 1.1.2 and Relay 1.0.5. I currently have a simple setup where players can choose to Host a new lobby or Join (only via code). Players authenticate anonymously with a random named profile beforehand. When using the same PC I can connect multiple clients to the same lobby from both the editor and from a build. When attempting to connect two PCs to the same lobby the same code does not work and I cannot figure out why.
Here is my simple Authentication class:
public class UnityAutheniticationService : BaseAuthenticationService
{
public override bool IsAuthenticated
=> _isAuthenticated;
private bool _isAuthenticated;
#if UNITY_EDITOR
private void OnDisable()
{
_isAuthenticated = false;
}
#endif
public override async UniTask<bool> TryAuthenticateAsync()
{
try
{
var initializationOptions = new InitializationOptions();
initializationOptions.SetProfile($"RandomProfile-{UnityEngine.Random.Range(0, 100000)}");
await UnityServices.InitializeAsync(initializationOptions);
AuthenticationService.Instance.SignedIn += OnSignedIn;
await AuthenticationService.Instance.SignInAnonymouslyAsync();
}
catch (Exception e)
{
Debug.LogError($"Failed to authenticate: {e}");
_isAuthenticated = false;
return false;
}
_isAuthenticated = true;
return true;
}
private void OnSignedIn()
{
AuthenticationService.Instance.SignedIn -= OnSignedIn;
Debug.LogError($"Signed in as: {AuthenticationService.Instance.PlayerId}");
}
public override void SignOut()
{
if (!AuthenticationService.Instance.IsSignedIn)
return;
AuthenticationService.Instance.SignOut();
_isAuthenticated = false;
}
}
Here is my simple host/join class:
public class UnityMatchService : BaseMatchService
{
private const int MaximumPlayerCount = 4;
public override bool IsConnected => _isConnected;
public override bool IsHost => NetworkManager.Singleton.IsHost;
public override bool IsClient => NetworkManager.Singleton.IsClient;
public override bool IsServer => NetworkManager.Singleton.IsServer;
public override ulong ClientId => NetworkManager.Singleton.LocalClientId;
public override IReadOnlyCollection<ulong> ClientIds => NetworkManager.Singleton.ConnectedClientsIds;
public override IMatchLobby Lobby => _lobby;
[SerializeField]
private GameObject _networkManagerPrefab;
[SerializeField]
private GameObject _onlineLobbyMenuNetworkBehaviourPrefab;
private UnityTransport _transport;
private UnityMatchLobby _lobby;
private bool _isConnected;
private NetworkObject _networkedLobbyObject;
private bool _awaitingSceneLoad;
public override async UniTask<bool> TryHostMatchAsync()
{
if (_transport == null)
CreateNetworkManagerObject(false);
try
{
var lobby = await LobbyService.Instance.CreateLobbyAsync(
$"Lobby-{UnityEngine.Random.Range(0, 100000)}",
MaximumPlayerCount,
new CreateLobbyOptions
{
IsPrivate = true
}
);
_lobby = new UnityMatchLobby(lobby, NetworkManager.Singleton.LocalClientId);
NetworkManager.Singleton.ConnectionApprovalCallback = ApprovalCheck;
var success = NetworkManager.Singleton.StartHost();
if (!success)
return success;
_networkedLobbyObject = Instantiate(_onlineLobbyMenuNetworkBehaviourPrefab).GetComponent<NetworkObject>();
_networkedLobbyObject.Spawn(true);
_isConnected = true;
SubscribeToNetworkSceneManager();
return _isConnected;
}
catch(Exception e)
{
Debug.LogError($"Failed to host match: {e}");
_isConnected = false;
return false;
}
}
public override async UniTask<bool> TryJoinMatch(string code)
{
if (_transport == null)
CreateNetworkManagerObject(false);
try
{
var lobby = await LobbyService.Instance.JoinLobbyByCodeAsync(
code,
new JoinLobbyByCodeOptions
{
Player = new Player(AuthenticationService.Instance.PlayerId)
}
);
Debug.Log($"Lobby: {lobby.Id}");
_lobby = new UnityMatchLobby(lobby, NetworkManager.Singleton.LocalClientId);
var success = NetworkManager.Singleton.StartClient();
Debug.Log($"Start client: {success}");
if (!success)
return success;
while (!NetworkManager.Singleton.IsConnectedClient)
{
await UniTask.NextFrame();
Debug.Log($"Waiting for IsConnectedClient...");
}
_isConnected = true;
Debug.Log($"Connected successfully!");
SubscribeToNetworkSceneManager();
return _isConnected;
}
catch(Exception e)
{
Debug.LogError($"Failed to join lobby: {e}");
_isConnected = false;
return false;
}
}
private void CreateNetworkManagerObject(bool simulateLatency)
{
_transport = Instantiate(_networkManagerPrefab).GetComponent<UnityTransport>();
if (simulateLatency)
_transport.SetDebugSimulatorParameters(
packetDelay: 50,
packetJitter: 2,
dropRate: 0
);
DontDestroyOnLoad(_transport.gameObject);
SubscribeToNetworkManager();
}
private void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
{
response.Approved = true;
response.CreatePlayerObject = true;
}
}
It is worth noting that when testing across multiple devices it appears that the join code gets stuck in the while (!NetworkManager.Singleton.IsConnectedClient) loop, indicating that this value is never set to true. I do not get any warning or errors when this occurs. Any ideas?