Skip to main content

Configure party settings

Last updated on October 24, 2024

After adding the party logic and implementing the UI to your game, you can start configuring the settings of the Party service.

Follow these steps:

  1. Inside PartyHandler.cs, add Unity Engine's UI library:

    using UnityEngine;
    using UnityEngine.UI;
  2. Add references to your Party UI:

    [SerializeField]
    private GameObject LobbyWindow;

    [SerializeField]
    private Transform canvasTransform;
    [SerializeField]
    private Transform partyDisplayPanel;

    [SerializeField]
    private GameObject partyInvitationPrefab;

    #region Buttons

    [SerializeField]
    private Button friendsManagementButton;
    [SerializeField]
    private Button createPartyButton;
    [SerializeField]
    private Button leavePartyButton;
    [SerializeField]
    private Button exitButton;

    #endregion

    [SerializeField]
    private Text partyIdText;
  3. Create a new dictionary that will save your Party members' User IDs and display names.

    public Dictionary<string, string> partyMembers { private set; get; }
  4. Since FriendsPanel can be called from both the Menu and the Lobby, create a new enum for an exit mode. In FriendsManagementHandler.cs, create a new enum with its getter and setter.

    #region ExitMode
    public enum ExitMode
    {
    Menu,
    Lobby
    }

    private ExitMode ExitScreen
    {
    get => ExitScreen;
    set
    {
    switch (value)
    {
    case ExitMode.Menu:
    FriendsManagementWindow.SetActive(false);
    GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
    break;

    case ExitMode.Lobby:
    FriendsManagementWindow.SetActive(false);
    GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
    break;
    }
    }
    }
    #endregion
  5. To avoid setting up the listener twice, add a new boolean as a flag checker in FriendsManagementHandler.cs, and then change the Setup() function:

    public void Setup(ExitMode exitType)
    {
    // Reset the exit button's listener, then add the listener based on the exit screen type
    exitButton.onClick.RemoveAllListeners();
    exitButton.onClick.AddListener(() =>
    {
    ...
    ExitScreen = exitType;
    });
    }
  6. Create a function in PartyHandler.cs to set up your Party UI when the LobbyPanel is set to active.

    /// Setup Party UI in Lobby and prepare state
    public void SetupParty()
    {
    friendsManagementButton.onClick.AddListener(() =>
    {
    GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Lobby);
    LobbyWindow.SetActive(false);
    GetComponent<FriendsManagementHandler>().FriendsManagementWindow.SetActive(true);
    });
    createPartyButton.onClick.AddListener(() => { CreateParty(); });
    leavePartyButton.onClick.AddListener(() => { LeaveParty(); });
    exitButton.onClick.AddListener(() =>
    {
    LobbyWindow.SetActive(false);
    GetComponent<MenuHandler>().Menu.gameObject.SetActive(true);
    });
    }

  7. Before you continue with PartyHandler.cs, connect the LobbyPanel with the MenuPanel's LobbyButton. In MenuHandler.cs, add a reference for the LobbyButton.

    public Button LobbyButton;
  8. Inside the Create() function, add the LobbyButton's event listener and change the FriendsButton's Setup():

    public void Create()
    {
    LobbyButton.onClick.AddListener(() =>
    {
    GetComponent<PartyHandler>().SetupParty();
    Menu.gameObject.SetActive(false);
    GetComponent<LobbyHandler>().LobbyWindow.SetActive(true);
    });

    FriendsButton.onClick.AddListener(() =>
    {
    GetComponent<FriendsManagementHandler>().Setup(FriendsManagementHandler.ExitMode.Menu);
    ...
    });
    }
  9. In the Unity Editor, on the MenuHandler.cs script component in the AccelByteHandler game object, drag the following objects to the appropriate variables.

  10. Go to FriendStatusPanel.cs and add an inviteToPartyButton listener in the SetupButton() function. Use the LobbyHandler's instance to get PartyHandler without needing to use the Find function.

    public void SetupButton()
    {
    inviteToPartyButton.onClick.AddListener(() =>
    {
    LobbyHandler.Instance.GetComponent<PartyHandler>().InviteToParty(_userData.userId);
    });
    ...
    }
  11. Update your PartyInvitationPanel.cs for when the PartyInvitationPopup is spawned, such as in the following example:

    // Add some UI references
    [SerializeField]
    private GameObject invitationPopUp;
    [SerializeField]
    private Text invitationText;
    [SerializeField]
    private Button acceptInvitationButton;
    [SerializeField]
    private Button rejectInvitationButton;

    // Create a function to setup the Popup and its listener
    public void Setup(PartyInvitation partyInvitation)
    {
    AccelByteSDK.GetClientRegistry().GetApi().GetUser().GetUserByUserId(partyInvitation.from, result =>
    {
    invitationText.text = result.Value.displayName + " invite you to join their party\nAccept invitation?";
    });

    acceptInvitationButton.onClick.AddListener(() => { JoinParty(partyInvitation);});
    rejectInvitationButton.onClick.AddListener(() => { RejectPartyInvitation(partyInvitation);});
    }
  12. Add the following in PartyInvitationPanel.cs to destroy the PartyInvitationPopup after the player accepts or rejects an invitation:

    public void JoinParty(PartyInvitation partyInvitation)
    {
    ...

    // Destroy the PopUp prefab
    Destroy(invitationPopUp);
    }

    public void RejectPartyInvitation(PartyInvitation partyInvitation)
    {
    ...

    // Destroy the PopUp prefab
    Destroy(invitationPopUp);
    }
  13. In the Unity editor, open the PartyInvitationPopup prefab. Add the PartyInvitationPanels.cs script as a component, then drag the objects to their exposed variables.

  14. In PartyHandler.cs, create a new function to Display Party data to the PartyListPanel using the BulkGetUserInfo() function to retrieve player data.

    /// Display all Party Data to PartyList UI
    public void DisplayPartyData(Result<PartyDataUpdateNotif> partyDataNotifResult)
    {
    // Update PartyID in UI
    partyIdText.text = "PartyID: " + partyDataNotifResult.Value.partyId;

    // Get all party members data based on _partyUserIds, then update data to UI
    AccelByteSDK.GetClientRegistry().GetApi().GetUser().BulkGetUserInfo(partyDataNotifResult.Value.members, result =>
    {
    if (result.IsError)
    {
    Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
    }
    else
    {
    // Initialize dictionary
    partyMembers = new Dictionary<string, string>();

    // Result data's order => reversed order of _partyIserIds
    int _index = result.Value.data.Length;
    foreach (BaseUserInfo user in result.Value.data)
    {
    _index -= 1;
    // Get transform of PlayerEntryDisplay, which is child of PartyListPanel
    Transform playerEntryDisplay = partyDisplayPanel.GetChild(_index).transform;

    if (user.userId == partyDataNotifResult.Value.leader)
    {
    // Set LeaderStatusIndicator as active
    Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
    leaderStatusIndicator.gameObject.SetActive(true);
    }
    else
    {
    if (AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId == partyDataNotifResult.Value.leader)
    {
    // Set PartyLeaderButton (promote button) as active, then add listener when onclick button
    Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
    partyLeaderButton.gameObject.SetActive(true);
    partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
    {
    PromotePartyLeader(user.userId);
    });

    // Set KickPartyButton as active, then add listener when onclick button
    Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
    kickPartyButton.gameObject.SetActive(true);
    kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
    {
    KickParty(user.userId);
    });
    }
    }

    // Set DisplayNameText as active, then change text to User's Display Name
    Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
    displayNameText.gameObject.SetActive(true);
    displayNameText.GetComponent<Text>().text = user.displayName;

    partyMembers.Add(user.userId, user.displayName);
    }
    }
    });
    }
  15. You may want to display Party Member data if the Lobby is still connected. You can do this by adding the Start() function and then add Display Party data functionality using GetPartyInfo().

    private void Start()
    {
    Lobby lobby = AccelByteSDK.GetClientRegistry().GetApi().GetLobby();
    if (lobby.IsConnected)
    {
    lobby.GetPartyInfo(partyInfoResult =>
    {
    // Update PartyID in the UI
    partyIdText.text = "PartyID: " + partyInfoResult.Value.partyID;

    ResetPlayerEntryUI();

    // Get all party members data based on _partyUserIds, then update data in the UI
    AccelByteSDK.GetClientRegistry().GetApi().GetUser().BulkGetUserInfo(partyInfoResult.Value.members, result =>
    {
    if (result.IsError)
    {
    Debug.Log($"Failed to get party member's data: error code: {result.Error.Code} message: {result.Error.Message}");
    }
    else
    {
    // Initialize dictionary
    partyMembers = new Dictionary<string, string>();

    // Result data's order => reversed order of _partyIserIds
    int index = result.Value.data.Length;
    foreach (BaseUserInfo user in result.Value.data)
    {
    index -= 1;
    // Get transform of PlayerEntryDisplay, which is child of PartyListPanel
    Transform playerEntryDisplay = partyDisplayPanel.GetChild(index).transform;

    if (user.userId == partyInfoResult.Value.leaderID)
    {
    // Set LeaderStatusIndicator as active
    Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
    leaderStatusIndicator.gameObject.SetActive(true);
    }
    else
    {
    if (AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId == partyInfoResult.Value.leaderID)
    {
    // Set PartyLeaderButton (promote button) as active, then add listener when onclick button
    Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
    partyLeaderButton.gameObject.SetActive(true);
    partyLeaderButton.GetComponent<Button>().onClick.AddListener(() =>
    {
    PromotePartyLeader(user.userId);
    });

    // Set KickPartyButton as active, then add listener when onclick button
    Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
    kickPartyButton.gameObject.SetActive(true);
    kickPartyButton.GetComponent<Button>().onClick.AddListener(() =>
    {
    KickParty(user.userId);
    });
    }
    }

    // Set DisplayNameText as active, then change text to User's Display Name
    Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
    displayNameText.gameObject.SetActive(true);
    displayNameText.GetComponent<Text>().text = user.displayName;

    partyMembers.Add(user.userId, user.displayName);
    }
    }
    });
    });
    }
    }
  16. Prepare some Reset functions to reset the Party data and UI in PartyHandler.cs:

    /// Reset Party ID's UI
    public void ResetPartyId()
    {
    partyIdText.text = "PartyID: ###############################";
    partyMembers = null;
    }

    /// Reset Party List's UI
    public void ResetPlayerEntryUI()
    {
    foreach(Transform playerEntryDisplay in partyDisplayPanel)
    {
    // Set LeaderStatusIndicator as not active
    Transform leaderStatusIndicator = playerEntryDisplay.GetChild(0).transform;
    leaderStatusIndicator.gameObject.SetActive(false);

    // Set PartyLeaderButton (promote button) as not active, then remove all listener on button
    Transform partyLeaderButton = playerEntryDisplay.GetChild(1).transform;
    partyLeaderButton.gameObject.SetActive(false);
    partyLeaderButton.GetComponent<Button>().onClick.RemoveAllListeners();

    // Set KickPartyButton as not active, then remove all listener on button
    Transform kickPartyButton = playerEntryDisplay.GetChild(2).transform;
    kickPartyButton.gameObject.SetActive(false);
    kickPartyButton.GetComponent<Button>().onClick.RemoveAllListeners();

    // Set DisplayNameText as not active and set value to default text
    Transform displayNameText = playerEntryDisplay.GetChild(3).transform;
    displayNameText.gameObject.SetActive(false);
    displayNameText.GetComponent<Text>().text = "PlayerUsername";
    }
    }
  17. The Party UI must be reset when a player leaves their current party, when displaying data, or on a player's first connection to the Lobby. To do this, call the Reset function in PartyHandler.cs:

    public void LeaveParty()
    {
    ResultCallback leavePartyCallback = result =>
    {
    if (result.IsError)
    {
    ...
    }
    else
    {
    ...
    // Reset all Party-related UIs
    ResetPartyId();
    ResetPlayerEntryUI();
    }
    };
    AccelByteSDK.GetClientRegistry().GetApi().GetLobby().LeaveParty(leavePartyCallback);
    }

    public void DisplayPartyData(Result<PartyDataUpdateNotif> partyDataNotifResult)
    {
    // Udate PartyID in UI
    ...

    // Reset the Party List's UI
    ResetPlayerEntryUI();

    ...
    }
  18. You will need the notification display to appear in the notification box. To do this, create a new script called LogMessagePanel.cs and attach it to the LogMessageDisplay prefab. Once completed, add the following to the script:

    using UnityEngine;
    using UnityEngine.UI;

    public class LogMessagePanel : MonoBehaviour
    {
    [SerializeField]
    private Text messageText;

    /// Update Notification Message's UI
    public void UpdateNotificationUI(string text, Color color)
    {
    messageText.text = text;
    messageText.color = color;
    }
    }
  19. In LobbyHandler.cs, add the following UI references:

    public GameObject LobbyWindow;

    #region Notification Box
    [Header("Notification Box")]
    [SerializeField]
    private Transform notificationBoxContentView;
    [SerializeField]
    private GameObject logMessagePrefab;
    #endregion
  20. Add the following function in LobbyHandler.cs. This function will be called to instantiate the log message in the notification box.

    /// Write the log message on the notification box
    public void WriteLogMessage(string text, Color color)
    {
    LogMessagePanel logPanel = Instantiate(logMessagePrefab, notificationBoxContentView).GetComponent<LogMessagePanel>();
    logPanel.UpdateNotificationUI(text, color);
    }
  21. In the Unity Editor, on your AccelByteHandler, drag the following objects to the exposed variables.

  22. In PartyHandler.cs, create functions to handle each update event in LobbyHandler.cs and to create notification messages.

    /// Called on update when a party invitation is received
    public void InvitePartyNotification(PartyInvitation partyInvitation)
    {
    Debug.Log($"Invited by: {partyInvitation.from}");
    PartyInvitationPanel invitationPanel = Instantiate(partyInvitationPrefab, canvasTransform).GetComponent<PartyInvitationPanel>();
    invitationPanel.Setup(partyInvitation);
    }

    /// Called on update when kicked from party
    public void KickPartyNotification()
    {
    Debug.Log("You're kicked from party");
    ResetPartyId();
    ResetPlayerEntryUI();
    }

    /// Called on update when a friend joins the party
    public void JoinedPartyNotification(JoinNotification joinNotification)
    {
    Debug.Log("Invitee join a party");
    AccelByteSDK.GetClientRegistry().GetApi().GetUser().GetUserByUserId(joinNotification.userID, result =>
    {
    if (result.IsError)
    {
    Debug.Log($"Failed to get user data: error code: {result.Error.Code} message: {result.Error.Message}");
    }
    else
    {
    LobbyHandler.Instance.WriteLogMessage($"[Party] {result.Value.displayName} join the party", Color.black);
    }
    });
    }

    /// Called on update when a friend leaves the party
    public void LeavePartyNotification(LeaveNotification leaveNotification)
    {
    if (leaveNotification.userID != AccelByteSDK.GetClientRegistry().GetApi().GetUser().Session.UserId)
    {
    Debug.Log($"{leaveNotification.userID} leave the party");
    LobbyHandler.Instance.WriteLogMessage($"[Party] {partyMembers[leaveNotification.userID]} leave the party", Color.black);
    }
    }
  23. While still in PartyHandler.cs, add the following code under the PromotePartyLeader() function to notify players whether their Promote Party Leader action succeeds or fails.

    public void PromotePartyLeader(string memberUserId)
    {
    // Instantiate the notification message
    NotificationMessagePanel notificationPanel = Instantiate(notificationMessagePrefab, notificationContentView).GetComponent<NotificationMessagePanel>();

    AccelByteSDK.GetClientRegistry().GetApi().GetLobby().PromotePartyLeader(memberUserId, result =>
    {
    if (result.IsError)
    {
    ...
    // Update the messageText that failed to promote leader
    LobbyHandler.Instance.WriteLogMessage($"[Party] Failed to promote {partyMembers[memberUserId]} to be party leader", Color.black);
    }
    else
    {
    ...
    // Update the messageText that success to promote leader
    LobbyHandler.Instance.WriteLogMessage($"[Party] Successfully promote {partyMembers[memberUserId]} to be party leader", Color.black);
    }
    });
    }
  24. Create new functions in NotificationHandler.cs that will be called from the notifications events when there is an update.

    // Collection of party notifications
    #region Party
    /// Called when user gets party invitation
    public void OnInvitedToParty(Result<PartyInvitation> result)
    {
    GetComponent<PartyHandler>().InvitePartyNotification(result.Value);
    }

    /// Called when user joins the party
    public void OnJoinedParty(Result<JoinNotification> result)
    {
    GetComponent<PartyHandler>().JoinedPartyNotification(result.Value);
    }

    /// Called when user is kicked by party leader
    public void OnKickedFromParty(Result<KickNotification> result)
    {
    GetComponent<PartyHandler>().KickPartyNotification();
    }

    /// Called when user leaves the party
    public void OnLeaveFromParty(Result<LeaveNotification> result)
    {
    GetComponent<PartyHandler>().LeavePartyNotification(result.Value);
    }

    /// Called when user rejects party invitation
    public void OnRejectedPartyInvitation(Result<PartyRejectNotif> result)
    {
    Debug.Log("[Party-Notification] Invitee rejected a party invitation");
    }

    /// Called when party data is updated
    public void OnPartyDataUpdateNotif(Result<PartyDataUpdateNotif> result)
    {
    GetComponent<PartyHandler>().DisplayPartyData(result);
    }
    #endregion
  25. Change your notification update events in LobbyHandler.cs under the ConnectToLobby() function, such as in the following example:

    public void ConnectToLobby()
    {
    ...
    // Party
    lobby.InvitedToParty += notificationHandler.OnInvitedToParty;
    lobby.JoinedParty += notificationHandler.OnJoinedParty;
    lobby.KickedFromParty += notificationHandler.OnKickedFromParty;
    lobby.LeaveFromParty += notificationHandler.OnLeaveFromParty;
    lobby.RejectedPartyInvitation += notificationHandler.OnRejectedPartyInvitation;
    lobby.PartyDataUpdateNotif += notificationHandler.OnPartyDataUpdateNotif;
    ...
    }
  26. Update the RemoveLobbyListeners() function in LobbyHandler.cs to reset the notification update events, such as in the following example:

    public void RemoveLobbyListeners()
    {
    ...
    // Party
    lobby.InvitedToParty -= notificationHandler.OnInvitedToParty;
    lobby.JoinedParty -= notificationHandler.OnJoinedParty;
    lobby.KickedFromParty -= notificationHandler.OnKickedFromParty;
    lobby.LeaveFromParty -= notificationHandler.OnLeaveFromParty;
    lobby.RejectedPartyInvitation -= notificationHandler.OnRejectedPartyInvitation;
    lobby.PartyDataUpdateNotif -= notificationHandler.OnPartyDataUpdateNotif;
    }
  27. Save and return to the Unity Editor. In your scene, on the AccelByteHandler gameObject, drag the appropriate objects into the exposed variables of the PartyHandler script component.

What's next?

Congratulations! You have now fully implemented the Party service.

On this page