Skip to main content

Matchmaking

Last updated on

Overview

AccelByte Gaming Services (AGS) Starter Matchmaking service provides a set of features developers can use to coordinate players into groups to participate in. The groups are based on selected preferences, such as game mode and language, and attributes stored for players, such as MMR, in order to provide well balanced competition.

How It Works

matchmaking

Party:

The Client asks the Session service to create a party. A Party Invitation notification is then relayed from the Session service through the Lobby.

Matchmaking:

The Client asks the Matchmaking service to request a match. The Matchmaking service then asks the Session service to create a session. Whether the session creation succeeds or fails, a notification will be conveyed back to the Client through the Lobby.

Manage Matchmaking in the Admin Portal

Create a Session Template

  1. In the Admin Portal, select your intended game title.

  2. In the left-hand menu, navigate to Game Management, expand New Matchmaking, and select Session Templates.

  3. Select + Add Session Template in the top right-hand corner.

    Matchmaking

    The Add Session Template form will appear.

  4. Fill in the following fields:

    Matchmaking

    • Session Template Name: enter a name for your session template.
    • Session Type: select the session type from the dropdown menu.
    • Min Players: set the minimum number of players allowed in the session.
    • Max Players: set the maximum number of players allowed in the session.
    • Invite Timeout: set the time limit (in seconds) before an invite from the session times out.
    • Inactive Timeout: set how long (in seconds) the session will wait before timing out a player that has not responded.
    • Joinability: select the joinability from the dropdown menu.
    • Requested Regions: select the regions this session can be used in from the dropdown menu.
  5. Once the form is completed, click Add to save your session.

Create a Match Ruleset

To learn how to create and configure Match Rules, you can access "Configure Match Rulesets" page, which is included in the preview for the new documentation portal.

Create a Match Pool

To learn how to create and configure Match Rules, you can access "Configure Match Pool" page, which is included in the preview for the new documentation portal.

Integrate Matchmaking into your Game Client

To learn more on how to integrate matchmaking into your game client, you can access "Integrating Matchmaking" page, which is included in the preview for the new documentation portal.

Implement Matchmaking Using the Client SDKs

Party

Create a Party

If the optional request is not filled, it will get the value from the configuration used.

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

FAccelByteModelsV2PartyCreateRequest Request;
Request.ConfigurationName = ConfigurationName; // MANDATORY
Request.Joinability = EAccelByteV2SessionJoinability::INVITE_ONLY; // Optional
Request.Members = {{OtherPartyMemberId}}; // Optional
Request.Attributes.JsonObject = MakeShared<FJsonObject>(); // Optional
Request.Attributes.JsonObject->SetStringField("PartyAttribute", "Attribute1"); // Optional
Request.MaxPlayers = 10; // Optional
Request.MinPlayers = 1; // Optional
Request.InactiveTimeout = 30; // Optional
Request.InviteTimeout = 86400; // Optional

ApiClient->Session.CreateParty(Request, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when create party success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when create party failed / error
}));

Retrieve parties

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.GetMyParties(THandler<FAccelByteModelsV2PaginatedPartyQueryResult>::CreateLambda(
[&](const FAccelByteModelsV2PaginatedPartyQueryResult& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Retrieve Party Details by Party ID

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.GetPartyDetails(PartyId, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Update Party Data

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

FAccelByteModelsV2PartyUpdateRequest Request;
Request.Version = PartyDataVersion; // Mandatory, must be the same version as latest party data
Request.Joinability = EAccelByteV2SessionJoinability::INVITE_ONLY; // Optional
Request.Attributes.JsonObject = MakeShared<FJsonObject>(); // Optional
Request.Attributes.JsonObject->SetStringField("PartyAttribute", "Attribute1"); // Optional
Request.MaxPlayers = 10; // Optional
Request.MinPlayers = 1; // Optional
Request.InactiveTimeout = 30; // Optional
Request.InviteTimeout = 86400; // Optional

ApiClient->Session.UpdateParty(PartyId, Request, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Invite Player to Party

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.SendPartyInvite(PartyId, UserIdToInvite, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Join a party

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.JoinParty(PartyId, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Reject a party invite

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.RejectPartyInvite(PartyId, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Leave a current party

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.LeaveParty(PartyId, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Kick a player from party

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.KickUserFromParty(PartyId, UserIdToKick, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Promote member to party leader

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.PromotePartyLeader(PartyId, NewPartyLeaderId, THandler<FAccelByteModelsV2PartySession>::CreateLambda(
[&](const FAccelByteModelsV2PartySession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when get my party failed / error
}));

Listen to party notifications

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Lobby.SetV2PartyInvitedNotifDelegate(Api::Lobby::FV2PartyInvitedNotif::CreateLambda(
[&](const FAccelByteModelsV2PartyInvitedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2PartyMembersChangedNotifDelegate(Api::Lobby::FV2PartyMembersChangedNotif::CreateLambda(
[&](const FAccelByteModelsV2PartyMembersChangedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2PartyJoinedNotifDelegate(Api::Lobby::FV2PartyJoinedNotif::CreateLambda(
[&](const FAccelByteModelsV2PartyUserJoinedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2PartyRejectedNotifDelegate(Api::Lobby::FV2PartyRejectedNotif::CreateLambda(
[&](const FAccelByteModelsV2PartyUserRejectedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2PartyKickedNotifDelegate(Api::Lobby::FV2PartyKickedNotif::CreateLambda(
[&](const FAccelByteModelsV2PartyUserKickedEvent& Notif)
{
// Do something when receive notification
}));

Game sessions

Create a game session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

FAccelByteModelsV2GameSessionCreateRequest Request;
Request.ConfigurationName = ConfigurationName; // MANDATORY
Request.Joinability = EAccelByteV2SessionJoinability::INVITE_ONLY; // Optional
Request.Type = EAccelByteV2SessionConfigurationServerType::DS; // Optional
Request.ClientVersion = GameServerVersion; // Optional
Request.ServerName = LocalServerName; // Optional
Request.Deployment = Deployment; // Optional
Request.RequestedRegions = {"us-west-1", "us-west2"}; // Optional

// Optional
TArray<FString> TeamA = {TeamAUserId1, TeamAUserId2};
TArray<FString> TeamB = {TeamBUserId1, TeamBUserId2};
TArray<FAccelByteModelsV2GameSessionTeam> Teams;
Teams.Add({TeamA});
Request.Teams = Teams;

// Optional
Request.Attributes.JsonObject = MakeShared<FJsonObject>();
Request.Attributes.JsonObject->SetStringField("PartyAttribute", "Attribute1");

Request.MaxPlayers = 10; // Optional
Request.MinPlayers = 1; // Optional
Request.InactiveTimeout = 30; // Optional
Request.InviteTimeout = 86400; // Optional


ApiClient->Session.CreateGameSession(Request,
THandler<FAccelByteModelsV2GameSession>::CreateLambda(
[&](const FAccelByteModelsV2GameSession& Result)
{
// Do something when operation success
}),
FErrorHandler::CreateLambda(
[&](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something when operation error / failed
}));

Retrieve game sessions

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.GetMyGameSessions(
THandler<FAccelByteModelsV2PaginatedGameSessionQueryResult>::CreateLambda(
[&](const FAccelByteModelsV2PaginatedGameSessionQueryResult& Result)
{
// Do something when operation success
}),
FErrorHandler::CreateLambda(
[&](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something when operation error / failed
}));

Retrieve game session details

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.GetGameSessionDetails( SessionId,
THandler<FAccelByteModelsV2GameSession>::CreateLambda(
[&](const FAccelByteModelsV2GameSession& Result)
{
// Do something when operation success
}),
FErrorHandler::CreateLambda(
[&](int32 ErrorCode, const FString& ErrorMessage)
{
// Do something when operation error / failed
}));

Update game session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

FAccelByteModelsV2GameSessionUpdateRequest Request;
Request.Version = PartyDataVersion; // Mandatory, must be the same version as current data in the backend
Request.Joinability = EAccelByteV2SessionJoinability::INVITE_ONLY; // Optional
Request.Attributes.JsonObject = MakeShared<FJsonObject>(); // Optional
Request.Attributes.JsonObject->SetStringField("AttributeName", "Attribute1"); // Optional
Request.MaxPlayers = 10; // Optional
Request.MinPlayers = 1; // Optional
Request.InactiveTimeout = 30; // Optional
Request.InviteTimeout = 86400; // Optional

ApiClient->Session.UpdateGameSession(GameSessionID, Request, THandler<FAccelByteModelsV2GameSession>::CreateLambda(
[&](const FAccelByteModelsV2GameSession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Delete a game session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();
ApiClient->Session.DeleteGameSession(SessionId, FVoidHandler::CreateLambda([]
{
// successfully deleted game session
}),
FErrorHandler::CreateLambda([](int32 ErrorCode, const FString& Message)
{
// error deleting game session
}));

Invite player to session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.SendGameSessionInvite(SessionId, UserIdToInvite, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Join a game session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.JoinGameSession(SessionId, THandler<FAccelByteModelsV2GameSession>::CreateLambda(
[&](const FAccelByteModelsV2GameSession& Result)
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Reject game session invite

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.RejectGameSessionInvite(GameSessionID, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Leave a game session

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Session.LeaveGameSession(SessionId, FVoidHandler::CreateLambda(
[&]
{
// do something when success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCode, const FString& Message)
{
// do something when failed / error
}));

Listen to game session notification

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->Lobby.SetV2GameSessionInvitedNotifDelegate(Api::Lobby::FV2GameSessionInvitedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSessionUserInvitedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2GameSessionMembersChangedNotifDelegate(Api::Lobby::FV2GameSessionMembersChangedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSessionMembersChangedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2GameSessionJoinedNotifDelegate(Api::Lobby::FV2GameSessionJoinedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSessionUserJoinedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2GameSessionRejectedNotifDelegate(Api::Lobby::FV2GameSessionRejectedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSessionUserRejectedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2GameSessionKickedNotifDelegate(Api::Lobby::FV2GameSessionKickedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSessionUserKickedEvent& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2GameSessionUpdatedNotifDelegate(Api::Lobby::FV2GameSessionUpdatedNotif::CreateLambda(
[&](const FAccelByteModelsV2GameSession& Notif)
{
// Do something when receive notification
}));

ApiClient->Lobby.SetV2DSStatusChangedNotifDelegate(Api::Lobby::FV2DSStatusChangedNotif::CreateLambda(
[&](const FAccelByteModelsV2DSStatusChangedNotif& Notif)
{
// Do something when receive notification
}));

Matchmaking

Create a match ticket

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

FAccelByteModelsV2MatchTicketOptionalParams Optionals;

Optionals.Attributes.JsonObject = MakeShared<FJsonObject>();
Optionals.Attributes.JsonObject->SetStringField("TestAttribute1", "AttributeValue");

Optionals.Latencies = ApiClient->Qos.GetCachedLatencies();
Optionals.SessionId = PartySessionId;

ApiClient->MatchmakingV2.CreateMatchTicket(MatchPoolName,
THandler<FAccelByteModelsV2MatchmakingCreateTicketResponse>::CreateLambda(
[&](const FAccelByteModelsV2MatchmakingCreateTicketResponse& Result)
{
// Do something when operation success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCodes, const FString& ErrorMessage)
{
// Do something when operation failed
}),
Optionals);

Get ticket details

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->MatchmakingV2.GetMatchTicketDetails(TicketID,
THandler<FAccelByteModelsV2MatchmakingGetTicketDetailsResponse>::CreateLambda(
[&](const FAccelByteModelsV2MatchmakingGetTicketDetailsResponse& Result)
{
// Do something when operation success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCodes, const FString& ErrorMessage)
{
// Do something when operation failed
}));

Delete match ticket

FApiClientPtr ApiClient = FMultiRegistry::GetApiClient();

ApiClient->MatchmakingV2.DeleteMatchTicket(TicketID,
FVoidHandler::CreateLambda([&]
{
// Do something when operation success
}),
FErrorHandler::CreateLambda([&](int32 ErrorCodes, const FString& ErrorMessage)
{
// Do something when operation failed
}));