How do I remove a player from a lobby when they close the window?

Hello, when a client closes their window, they are not leaving the lobby. This is a particularly big problem if they are the host, because then the host never transfers to anyone else.

I tried to make the client leave like this:

    void OnApplicationQuit() {
        Debug.Log("QUIT");

        Leave();
    }

    async void Leave() {
        await LobbyService.Instance.RemovePlayerAsync(LobbyManager.Instance.joinedLobby.Id, AuthenticationService.Instance.PlayerId);
    }

The log did appear, but the client did not leave the lobby. This also didn’t work:

    void OnApplicationQuit() {
        Debug.Log("QUIT");

        LobbyService.Instance.RemovePlayerAsync(LobbyManager.Instance.joinedLobby.Id, AuthenticationService.Instance.PlayerId);
    }

I’m not sure what else to try. Any ideas would be much appreciated, thanks!

Hi @kadenjantz ,
You have to set “Disconnect Removal Time” variable to 10 second. 10 is minimum value.
This properties is in the Dashboard=>Lobby =>Config page.

Looks like this is a pretty old thread but I also ran into this problem when testing project. I configured the lobby as suggested above with no effect.
I came up with this solution after looking at the example lobby project that Unity provides.

Objective: Ensure that when the application is attempting to quit, any player that has joined a lobby is properly removed before the application fully exits.

Implementation:

  • Event Subscription:

  • During initialization (UnityGameServicesInitializer_OnInitialized method), we subscribe to the Application.wantsToQuit event. This event is triggered when the application is preparing to exit.

  • Checking Lobby Status:

  • In the Application_wantsToQuit event handler, we evaluate if the player is currently in a lobby using the HasJoinedLobby() method.

  • If the player has not joined a lobby, the method will immediately allow the application to exit by returning true for canQuit.

  • If the player is in a lobby, we initiate the process to remove the player from the lobby by invoking the LeaveBeforeQuit coroutine.

  • Player Removal Process:

  • The LeaveBeforeQuit coroutine initiates the RemovePlayerAsync method, which is responsible for the asynchronous task of removing the player from the lobby.

  • We then pause the coroutine execution and wait until the removal task is completed using the WaitUntil method.

  • Once the player is successfully removed, the Application.Quit() method is called again to exit the application.

  • Asynchronous Player Removal:

  • The RemovePlayerAsync method uses Unity’s LobbyService to perform the asynchronous operation of removing the player from the specified lobby.

  • If the removal is successful, we reset the joinedLobby to null.

  • In case of any exceptions or errors during this process, an error message is logged.

Outcome: Through this approach, we ensure that any player in a lobby is gracefully removed before the application terminates. If the removal is successful, the application is allowed to quit, ensuring a clean exit.

protected override void UnityGameServicesInitializer_OnInitialized()
        {
            base.UnityGameServicesInitializer_OnInitialized();
            Application.wantsToQuit += Application_wantsToQuit;
            StartCoroutine(HeartbeatCouroutine());
        }
private bool Application_wantsToQuit()
        {
            bool canQuit = !HasJoinedLobby();
            if (HasJoinedLobby())
            {
                StartCoroutine(LeaveBeforeQuit(joinedLobby.Id, AuthServiceHandler.UnityAuthorizationServicePlayerId));
            }
            return canQuit;
        }
IEnumerator LeaveBeforeQuit(string lobbyId, string playerId)
        {
            var task = RemovePlayerAsync(lobbyId, playerId);
            yield return new WaitUntil(() => task.IsCompleted);
            Application.Quit();
        }
private async Task RemovePlayerAsync(string lobbyId, string playerId)
        {
            if (!IsServiceReady) return;
            try
            {
                await LobbyService.Instance.RemovePlayerAsync(lobbyId, playerId);
                joinedLobby = null;
            }
            catch
            {
                Debug.LogError("Failed to remove player");
            }
        }
1 Like

where is the dashboard ?

where should i put that script ?

Dont know why they limit the Lobby too much, only Host can access things while Host is disconnected from a device couldn’t detect the Quit,so nobody can not access that lobby any more that gave too many reconnect/disconnect issues … on Steam lobby, it is very easy to handle.

Thank you very much!

Here’s an example

public class LobbyManager : MonoBehaviour
{
    // Your existing code...

    private void Start()
    {
        Application.wantsToQuit += Application_wantsToQuit;
        try
        {
            await InitializeUnityServicesAsync();
        }
        catch (Exception e)
        {
            HandleError("Failed to initialize Unity Services", e);
        }
    }

    private void OnDestroy()
    {
        Application.wantsToQuit -= Application_wantsToQuit;
    }

    private bool Application_wantsToQuit()
    {
        bool canQuit = currentLobby == null;
        if (currentLobby != null)
        {
            StartCoroutine(LeaveBeforeQuit());
        }
        return canQuit;
    }

    private IEnumerator LeaveBeforeQuit()
    {
        var task = ForceCleanupLobbyAsync();
        yield return new WaitUntil(() => task.IsCompleted);
        Application.Quit();
    }

    private async Task ForceCleanupLobbyAsync()
    {
        if (currentLobby == null) return;

        try
        {
            if (IsLobbyHost())
            {
                await LobbyService.Instance.DeleteLobbyAsync(currentLobby.Id);
                Debug.Log("Successfully deleted lobby during quit");
            }
            else
            {
                await LobbyService.Instance.RemovePlayerAsync(currentLobby.Id, AuthenticationService.Instance.PlayerId);
                Debug.Log("Successfully left lobby during quit");
            }
            currentLobby = null;
        }
        catch (Exception e)
        {
            Debug.LogError($"Failed to cleanup lobby during quit: {e.Message}");
        }
    }
}