Last Updated: 9/15/2022, 3:30:25 AM

# Lobby

# Overview

The AccelByte Lobby service provides continuous connection between your game and players by using WebSocket. WebSocket ensures reliable, real-time data transfer by allowing two-way communication between the server and clients. Since the Lobby serves as the main hub of your game, it is related to many of our other services, including:

  • Presence enables players to see what other players are doing in real-time. This feature is critical in online multiplayer games, because player interactions rely on knowing which players are available.
  • Party is used as the basis for multiplayer matchmaking. Parties can be integrated with other services such as Presence, Friends, and Chat, for a more engaging and fun multiplayer experience.
  • Friends lets players connect and interact with each other. AccelByte supports both in-game friends and platform level friends. In-game friends can chat and play together within a game, whereas platform level friends allow players of different games to interact with each other on your web platform.
  • Chat enables real-time text-based communication in-game. We support global, party, and individual chat.

# Manage the Lobby in the Admin Portal

# Configure the Lobby

  1. In the Admin Portal, open your game namespace, go to the Game Management section, click on the Lobby Configuration menu on the left-hand side.

    lobby

  2. On the Lobby Configuration page, you can configure your game’s Lobby by adjusting the settings below:

    lobby

    # Lobby Concurrent User (CCU)

    Lobby Concurrent User (CCU) shows the total number of active players. This value is refreshed once every minute.

    lobby

    # Configuration

    This section includes general Lobby settings.

    lobby

    • Keep Player’s Activity determines whether a player's activity data is kept after they disconnect from the Lobby. Toggle this option On to save the player’s activity upon disconnection.
    • Cancel Match on Disconnect determines what happens to a player’s match when that player disconnects. Toggle this option On if you want the matchmaking request to be canceled if a player disconnects, or Off if you want the matchmaking request to remain active even when the player has been disconnected.
    • Ready Consent Timeout (Sec) determines how long a player has to confirm that they’re ready to start the match, in seconds. If the player doesn’t confirm that they’re ready before the timeout, their matchmaking request will be canceled. The default value is 20 seconds.
    • Max Player in the Lobby determines the maximum number of players that can join the Lobby at any one time. The default value is -1, which means that an unlimited number of players can join the Lobby.

    # Party Configuration

    This section contains Party settings.

    lobby

    • Max. Party Member determines how many players can join a party.
    • Auto Kick on Disconnect determines what happens to a player’s party membership if they are disconnected from the game. If this setting is toggled Off, players will not be removed from their party when they are disconnected. If this setting is toggled On, the player will be removed from their party if they are disconnected.
    • Auto Kick Delay Time is used to add a delay before a player is kicked from their party upon being disconnected from the game. To add a delay, toggle this setting on and type the desired delay time (in seconds). If the delay time is set to 0, the player will be removed from their party immediately when they are disconnected.

    NOTE

    These settings also apply to party leaders. If the party leader is removed from their party, the player that has been in the party longest will be automatically promoted to party leader.

    # Chat Rate Limit

    This section contains Chat settings. The Chat Rate Limit Duration and Chat Rate Limit Burst settings work together to limit how many messages players can send in the chat, to prevent spamming.

    lobby

    • Chat is used to enable or disable the chat feature in your game. This setting is enabled by default.
    • Chat Rate Limit Duration (ms) is the amount of time (in milliseconds) that is used to determine when messages are considered spam. This setting works with the Chat Rate Limit Burst setting.
    • Chat Rate Limit Burst is the number of messages that a player can send within a given time period before they receive an error. This setting works with the Chat Rate Limit Duration setting.

    When combined, these two settings determine a rate of messages per unit of time. For example, if the Chat Rate Limit Duration is 1,000 milliseconds and the Chat Rate Limit Burst is 3, then 3 messages per 1,000 milliseconds (1 second) is the rate at which sent messages are considered spam by the Lobby service. This means that chat messages that are sent at a rate of less than 3 messages per second will be sent normally and not considered spam.

    # Entitlement Check

    This section contains Entitlements settings.

    lobby

    • Entitlement Check determines whether the backend will check if a player has the necessary entitlements before they are granted access to the Lobby. This can be used as an additional layer of security to prevent players from accessing games if they have obtained access to a Client ID and Client Secret that allows them to access your game, even if they haven’t purchased it.
    • Item Name determines which item will be used in the Entitlement Check.

    # Lobby Service Rate Limit

    These settings work together to determine how many requests a player can make to the Lobby service before an error is returned.

    lobby

    • Duration Limit (ms) determines the duration (in milliseconds) in which requests made to the Lobby service may return an error. This setting works with the Burst Limit setting.
    • Burst Limit determines the number of requests that can be made to the Lobby service within a given time. This setting works with the Duration Limit setting.

    When combined, these two settings determine a rate of requests per unit of time. For example, if the Duration Limit is 1,000 milliseconds and the Burst Limit is 3, then 3 requests per 1,000 milliseconds (or per second) is the minimum rate at which requests sent to the Lobby will be considered spam by the Lobby service. This means that requests that are made at a rate of less than 3 per second will be handled normally and not considered spam.

# Export Lobby Configuration

  1. In the Admin Portal open the desired game namespace, then go to the Game Management section and open the Lobby Configuration menu.

    lobby

  2. On the Lobby Configuration page, click Export/Import Configuration in the top-right corner of the page, then click Export Lobby Configuration.

    lobby

  3. The lobby configuration of the selected game namespace will be downloaded to your computer in JSON format.

# Import Lobby Configuration

  1. In the Admin Portal open the desired game namespace, then go to the Game Management section and open the Lobby Configuration menu.

    lobby

  2. On the Lobby Configuration page, click Export/Import Configuration in the top-right corner of the page, then click Import Lobby Configuration.

    lobby

  3. The Import Lobby Configuration form appears. Click Select JSON File to browse for the lobby configuration you want to import, then click the Import button.

    lobby

  4. The selected lobby configuration will be imported.

# Implement the Lobby using the Client SDKs

# Connect to the Lobby

You can connect the AccelByte Lobby service to your game by using the command below:

Once you have set up a Lobby connection, you will be able to implement social features like Presence, Party, Friends, and Chat.

# Handle the Connect/Disconnect Event

This feature notifies the game of any changes to the connection to the Lobby server. The SDK already provides an auto-reconnect mechanism, but when the auto-reconnect times out you must reconnect manually.

You can use Reject Consent in matchmaking so players can reject a match after they have been matched. This gives players the chance to reject matches right away instead of waiting for the ready consent timer to expire.

# Implement the Lobby using the Unity SDK

# Quick Reference

References
using AccelByte.Api;
using AccelByte.Core;
using AccelByte.Models;
Connection Notification Events
lobby.Connected += delegate { };
lobby.Disconnecting += result => { };
lobby.Disconnected += result => { };
Lobby Connect
lobby.Connect();
Lobby Disconnect
AccelBytePlugin.GetLobby().Disconnect();
Check if Lobby is Connected
AccelBytePlugin.GetLobby().IsConnected

# Quickstart Guide

In this tutorial, you will learn how to use the Lobby Services. This guide assumes that you have already implemented the Login IAM (opens new window).

  1. Create a new script called LobbyHandler.cs and attach it to the AccelByteHandler gameObject.

  2. Add the following AccelByte libraries to the top of the script:

using AccelByte.Api;
  1. Create a function called ConnectToLobby() and take a reference of the Lobby (even though the Lobby is not connected at this point).
// Get a reference to the instance of the Lobby
Lobby lobby = AccelBytePlugin.GetLobby();
  1. Add the following functions to notify the player when the Lobby has been Connected, Disconnected, or is Disconnecting.
// Connection
lobby.Connected += () =>{ Debug.Log("Lobby Connected"); };
lobby.Disconnecting += result => { Debug.Log($"Lobby Disconnecting {result.Value.message}");};
lobby.Disconnected += result => { Debug.Log($"Lobby Disconnected: {result}");};

The Lobby system is built around actions and callbacks, so be sure to check the signatures of the Event that you're subscribing to. For more information, you can find these models in LobbyModels.cs within the Plugin folder.

In this example, you only need to log a message or, in the case of Disconnecting and Disconnected, use the result to give the player more information.

  1. Once this basic functionality is incorporated, connect the Lobby. This action opens a WebSocket that you will want to tightly control the lifecycle of. At the end of this function, add the following code:
//Connect to the Lobby
if (!_lobby.IsConnected)
{
    _lobby.Connect();
}
  1. To disconnect from the Lobby, use a reusable function to check if the Lobby is Connected, and if it is, Disconnect:
public void DisconnectFromLobby()
{
    if (AccelBytePlugin.GetLobby().IsConnected)
    {
        AccelBytePlugin.GetLobby().Disconnect();
    }
}

To ensure the WebSocket is closed when the game stops or when you stop using the Unity Editor, add DisconnectFromLobby() to the OnApplicationQuit() function.

private void OnApplicationQuit()
{
   DisconnectFromLobby();
}
  1. Add the other callbacks to the ConnectToLobby() function. Your final function should look like this:
public void ConnectToLobby()
{
    // Get a reference to the instance of the Lobby
    Lobby lobby = AccelBytePlugin.GetLobby();

    // Connection
    lobby.Connected += () => { Debug.Log("Lobby Connected"); };
    lobby.Disconnecting += result =>  { Debug.Log($"Lobby Disconnecting {result.Value.message}");};
    lobby.Disconnected += result => { Debug.Log($"Lobby Disconnected: {result}"); };

    // Connect to the Lobby
    lobby.Connect();

}
  1. Test your code by running the function after successfully connecting to the Lobby.

Return to LoginHandler.cs and add the following code to the success section of the user.LoginWithUsername() delegate:

...
else
{
    Debug.Log("Login successful");

    // Attempt to Connect to Lobby
    GetComponent<LobbyHandler>().ConnectToLobby();
...

Return to the Unity Editor and press Play. If you have configured your code correctly, you should see the message Lobby Connected after successfully logging in.

Congratulations! You have successfully connected to the Lobby.

Continue on for a step by step example of the UI and code implementation. Otherwise, you are now ready to move on to the Friends Service (opens new window).

# Step by Step Guide

Code Implementation

Now that you have some basic Lobby functionalities in place, it’s time to tidy up your code. Follow the Singleton Pattern for this and all future handler classes.

  1. Add the following code to the top of your LobbyHandler.cs class:
/// Private Instance
static LobbyHandler _instance;

/// The Instance Getter
public static LobbyHandler Instance => _instance;

/// Reference to Lobby in Handler
public Lobby _lobby;


private void Awake()
{
    // Check if another Instance is already created, and if so delete this one, otherwise destroy the object
    if (_instance != null && _instance != this)
    {
        Destroy(this);
        return;
    }
    else
    {
        _instance = this;
    }  
}
  1. Change the GetLobby line in ConnectToLobby to the following code:
// Get a reference to the instance of the Lobby
_lobby = AccelBytePlugin.GetLobby();

Change all the subsequent mentions of lobby to _lobby.

  1. Open your LoginHandler.cs class. In the OnLoginClick() function, replace GetComponent<LobbyHandler>().ConnectToLobby; with LobbyHandler.Instance.ConnectToLobby();.
...
else
{
    Debug.Log("Login successful");

    // Attempt to Connect to Lobby
    LobbyHandler.Instance.ConnectToLobby();
...
  1. Create a new script called NotificationHandler.cs and add the AccelByte libraries to the top of the script:
using AccelByte.Models;
using AccelByte.Core;
  1. While still in NotificationHandler.cs, create new functions for each notification:
public class NotificationHandler : MonoBehaviour
{
    // Collection of connection notifications
    #region Connections
    /// Called when lobby is connected
    public void OnConnected()
    {
            Debug.Log("Lobby Connected");
    }

    /// Called when connection is disconnecting
    /// <param name="result"> Contains data of message</param>
    public void OnDisconnecting(Result<DisconnectNotif> result)
    {
            Debug.Log($"Lobby Disconnecting {result.Value.message}");
    }

    /// Called when connection is being disconnected
    /// <param name="result"> Contains data of websocket close code</param>
    public void OnDisconnected(WsCloseCode result)
    {
            Debug.Log($"Lobby Disconnected: {result}");
    }
    #endregion
}
  1. In LobbyHandler.cs, add the following code to obtain the NotificationHandler’s component.
...
[HideInInspector]
public NotificationHandler notificationHandler;

private void Awake()
{
    ...

    // Get the the object handler
        notificationHandler = gameObject.GetComponent<NotificationHandler>();
}
  1. In LobbyHandler.cs, change the delegate in ConnectToLobby() by calling the functions you created earlier in NotificationHandler.cs.
public void ConnectToLobby()
{
        ...

        // Connection
        _lobby.Connected += notificationHandler.OnConnected;
        _lobby.Disconnecting += notificationHandler.OnDisconnecting;
        _lobby.Disconnected += notificationHandler.OnDisconnected;

        ...
}
  1. While still in LobbyHandler.cs, add a new function to remove the delegate to reset the listener:
public void RemoveLobbyListeners()
{
    //Remove delegate from Lobby
    //Connection
    _lobby.Connected -= notificationHandler.OnConnected;
    _lobby.Disconnecting -= notificationHandler.OnDisconnecting;
    _lobby.Disconnected -= notificationHandler.OnDisconnected;
}

Congratulations! You have now fully implemented the Lobby connection, which is the gateway to many of AccelByte’s services using WebSocket.

Proceed to the next section to learn how to implement the Friends Service (opens new window).

# Full Code

LobbyHandler.cs
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

using UnityEngine;
using AccelByte.Api;

public class LobbyHandler : MonoBehaviour
{
    /// <summary>
    /// Private Instance
    /// </summary>
    static LobbyHandler _instance;

    /// <summary>
    /// The Instance Getter
    /// </summary>
    public static LobbyHandler Instance => _instance;

    /// <summary>
    /// The Instance Getter
    /// </summary>
    private Lobby _lobby;

    [HideInInspector]
    public NotificationHandler notificationHandler;


    private void Awake()
    {
        // Check if another Instance is already created, and if so delete this one, otherwise destroy the object
        if (_instance != null && _instance != this)
        {
            Destroy(this);
            return;
        }
        else
        {
            _instance = this;
        }

        // Get the the object handler
        notificationHandler = gameObject.GetComponent<NotificationHandler>();
    }

    /// <summary>
    /// Connect to the <see cref="Lobby"/> and setup CallBacks
    /// </summary>
    public void ConnectToLobby()
    {
        //Get a reference to the instance of the Lobby
        _lobby = AccelBytePlugin.GetLobby();

        //Connection
         _lobby.Connected += notificationHandler.OnConnected;
         _lobby.Disconnecting += notificationHandler.OnDisconnecting;
         _lobby.Disconnected += notificationHandler.OnDisconnected;

        //Connect to the Lobby
        if (!_lobby.IsConnected)
        {
            _lobby.Connect();
        }
    }

    public void RemoveLobbyListeners()
    {
        //Remove delegate from Lobby
        //Connection
        _lobby.Connected -= notificationHandler.OnConnected;
        _lobby.Disconnecting -= notificationHandler.OnDisconnecting;
        _lobby.Disconnected -= notificationHandler.OnDisconnected;
    }

    public void DisconnectFromLobby()
    {
        if (AccelBytePlugin.GetLobby().IsConnected)
        {
            AccelBytePlugin.GetLobby().Disconnect();
        }
    }

    private void OnApplicationQuit()
    {
        // Attempt to Disconnect from the Lobby when the Game Quits
        DisconnectFromLobby();
    }
}
NotificationHandler.cs
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

using UnityEngine;
using AccelByte.Models;
using AccelByte.Core;

public class NotificationHandler : MonoBehaviour
{
    #region Notifications

    // Collection of connection notifications
    #region Connections
    /// <summary>
    /// Called when lobby is connected
    /// </summary>
    public void OnConnected()
    {
        Debug.Log("Lobby Connected");
    }

    /// <summary>
    /// Called when connection is disconnecting
    /// </summary>
    /// <param name="result"> Contains data of message</param>
    public void OnDisconnecting(Result<DisconnectNotif> result)
    {
        Debug.Log($"Lobby Disconnecting {result.Value.message}");
    }

    /// <summary>
    /// Called when connection is being disconnected
    /// </summary>
    /// <param name="result"> Contains data of websocket close code</param>
    public void OnDisconnected(WsCloseCode result)
    {
        Debug.Log($"Lobby Disconnected: {result}");
    }
    #endregion

    #endregion
}
LoginHandler.cs
// Copyright (c) 2021 - 2022 AccelByte Inc. All Rights Reserved.
// This is licensed software from AccelByte Inc, for limitations
// and restrictions contact your company contract manager.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using AccelByte.Api;
using AccelByte.Models;
using AccelByte.Core;
using UnityEngine.Serialization;
using UnityEngine.UI;

public class LoginHandler : MonoBehaviour
{
    /// <summary>
    /// Private Instance
    /// </summary>
    static LoginHandler _instance;
    /// <summary>
    /// The Instance Getter
    /// </summary>
    public static LoginHandler Instance => _instance;
    private void Awake()
    {
        //Check if another Instance is already created, and if so delete this one, otherwise destroy the object
        if (_instance != null && _instance != this)
        {
            Destroy(this);
            return;
        }
        else
        {
            _instance = this;
        }

    }

    [SerializeField]
    Button loginButton;
    [SerializeField]
    Text statusText;
    [SerializeField]
    InputField usernameInputField;
    [SerializeField]
    InputField passwordInputField;
    [SerializeField]
    RectTransform loginPanel;

    private void OnEnable()
    {
        //When we Activate, set the Text of the Login Status
        //and add the Login Call to the Button's listener
        statusText.text = "Please Login";
        loginButton.onClick.AddListener(()
            =>
        {
            statusText.text = "Attempting Login";
            OnLoginClick(usernameInputField.text, passwordInputField.text);
        });
    }

    private void OnDisable()
    {
        //When we disable, clear all of the Listeners from the Login Button
        loginButton.onClick.RemoveAllListeners();
    }


    /// <summary>
    /// Function called to Login to AccelByte's IAM services
    /// </summary>
    /// <param name="username">The Username (typically an email address) of the user</param>
    /// <param name="password">The password of the user</param>
    public void OnLoginClick(string username, string password)
    {
        //Disable Interaction with the Login Button so the player cannot spam click it and send multiple requests
        loginButton.interactable = false;
        statusText.text = "Logging in...";
        //Grab a reference to the current User, even though they have not been logged in yet.
        //This also acts as the initialisation point for the whole AccelByte plugin.
        User user = AccelBytePlugin.GetUser();
        //Calling the Login Function and supplying a callback to act upon based upon success or failure
        //You will almost certainly want to extend this functionality further
        //Note that this callback is asynchronous
        user.LoginWithUsername(username, password,
            result =>
            {
                if (result.IsError)
                {
                    //If we error, grab the Error Code and Message to print in the Log
                    Debug.Log($"Login failed : {result.Error.Code}: {result.Error.Message}");
                    //Set the Status Text to display the Error if there is any
                    statusText.text = $"Login failed : {result.Error.Code}: {result.Error.Message}";
                }
                else
                {
                    Debug.Log("Login successful");

                    //Attempt to Connect to Lobby
                    LobbyHandler.Instance.ConnectToLobby();
                    //This is where we connect to Lobby
                    loginPanel.gameObject.SetActive(false);
                }

                //Enable interaction with the Button again
                loginButton.interactable = true;
            });
    }
}