GS2-Matchmaking SDK for Game Engine API Reference

Specifications of models and API references for GS2-Matchmaking SDK for Game Engine

Model

EzGathering

Gathering

An entity representing a group of game players brought together by matchmaking. It has multiple parameters for matchmaking, and the players are grouped based on the totality of the parameters. Players join a Gathering by specifying their role, attributes, and optionally a blacklist of users they do not wish to play with. Joining is validated against attribute range requirements, role capacity limits, and whitelist restrictions (allowUserIds). When all role slots are filled to capacity, the Gathering is considered complete and matchmaking finishes. Gathering names are automatically generated in UUID format, and an optional expiration time can be set for automatic cleanup.

TypeConditionRequiredDefaultValue LimitsDescription
gatheringIdstring
*
~ 1024 charsGathering GRN
* Set automatically by the server
namestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
attributeRangesList<EzAttributeRange>[]0 ~ 5 itemsRecruitment Requirements
A list of attribute range conditions that players must satisfy to join this Gathering.
Each entry specifies a named attribute and its acceptable min/max range.
A player’s own attribute values must fall within these ranges to participate. Maximum 5 conditions.
capacityOfRolesList<EzCapacityOfRole>[]1 ~ 5 itemsList of Role Capacities
Defines the recruitment slots for this Gathering.
Each entry specifies a role name, its aliases, and the maximum number of players that can fill that role.
When all role slots reach their capacity, matchmaking is considered complete. At least 1, maximum 5 roles.
allowUserIdsList<string>[]0 ~ 100 itemsAllowed User IDs
A whitelist of user IDs that are permitted to join this Gathering.
When specified, only the listed users can participate in matchmaking for this Gathering.
Useful for friend-only or invitation-based matchmaking scenarios. Maximum 100 entries.
metadatastring~ 1024 charsMetadata
Arbitrary values can be set in the metadata.
Since they do not affect GS2’s behavior, they can be used to store information used in the game.
expiresAtlongGathering Expiration Time
The time at which this Gathering automatically expires and is deleted.
If matchmaking does not complete before this time, the Gathering is cleaned up.
When not specified, the Gathering persists until matchmaking completes or it is manually deleted.
createdAtlong
*
NowDatetime of creation
Unix time, milliseconds
* Set automatically by the server
updatedAtlong
*
NowDatetime of last update
Unix time, milliseconds
* Set automatically by the server

EzRating

Rating

An entity that holds the current rating value for each game player. Created automatically when a player first participates in rated matchmaking. The rating is calculated using the Glicko-2 algorithm, with an initial rate value and rating deviation (rd) that represents the uncertainty of the rating. The rate value converges toward the player’s true skill level as more matches are played.

TypeConditionRequiredDefaultValue LimitsDescription
ratingIdstring
*
~ 1024 charsRating GRN
* Set automatically by the server
namestring
~ 128 charsRating name
Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
userIdstring
~ 128 charsUser ID
rateValuefloat1500.00 ~ 65535.0Rate Value
The player’s current rating score calculated by the Glicko-2 algorithm.
Defaults to the initial value defined in the RatingModel (typically 1500.0).
The value increases or decreases based on match results and the relative strength of opponents.
createdAtlong
*
NowDatetime of creation
Unix time, milliseconds
* Set automatically by the server
updatedAtlong
*
NowDatetime of last update
Unix time, milliseconds
* Set automatically by the server

EzJoinedSeasonGathering

Joined Season Gathering

A record that tracks which Season Gathering a player has joined within a specific season and tier. Created automatically when a player joins a Season Gathering, serving as an index to quickly look up the player’s current gathering. Each player can belong to at most one Season Gathering per season and tier combination.

TypeConditionRequiredDefaultValue LimitsDescription
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonlong
0 ~ 9223372036854775805Season
tierlong
0 ~ 9223372036854775805Tier
The tier level used to group players of similar rank together.
Determined by the player’s rank in the GS2-Experience model specified in the SeasonModel.
Players are only matched with others in the same tier, ensuring fair competition.
seasonGatheringNamestring
~ 128 charsSeason Gathering Name
The name of the Season Gathering that this player has joined.
Used to reference the specific Season Gathering entity within the same season and tier.

EzSeasonGathering

Season Gathering

A persistent gathering within a season that collects players over the season period. Unlike regular Gatherings that dissolve once matchmaking completes, Season Gatherings persist throughout the season and accumulate participants. Players are grouped by tier (based on GS2-Experience rank) and season number, and each Season Gathering has a maximum participant limit defined by the SeasonModel.

TypeConditionRequiredDefaultValue LimitsDescription
seasonGatheringIdstring
*
~ 1024 charsSeason Gathering GRN
* Set automatically by the server
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonlong
0 ~ 9223372036854775805Season
tierlong
0 ~ 9223372036854775805Tier
The tier level used to group players of similar rank together.
Determined by the player’s rank in the GS2-Experience model specified in the SeasonModel.
Players are only matched with others in the same tier, ensuring fair competition.
namestring
UUID~ 128 charsSeason Gathering Name
Season Gathering-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
participantsList<string>[]0 ~ 1000 itemsList of Participant User IDs
The list of user IDs of players who have joined this Season Gathering.
Players are added to this list when they join and the list grows throughout the season until the maximum participant limit is reached.

EzBallot

Ballot

A ballot paper issued to each player for reporting match results after a rated matchmaking game. Contains the context of the match: the rating model name, gathering name, and number of players. Each player receives a ballot signed by the server, which they fill in with game results and submit to the Vote API. The voting system requires more than 50% consensus among submitted ballots to finalize rating calculations.

TypeConditionRequiredDefaultValue LimitsDescription
userIdstring
~ 128 charsUser ID
ratingNamestring
~ 128 charsRating Name
The name of the RatingModel to use for rating calculations after this match.
Identifies which rating system’s parameters (initial value, volatility) apply to this match’s result processing.
gatheringNamestring
~ 128 charsGathering Name
The name of the Gathering for which match results are being reported.
Used to identify the specific matchmaking session and correlate votes from all participants in the same match.
numberOfPlayerint
2 ~ 10Number of Players
The total number of players who participated in this match.
Used to determine the expected number of ballots and validate consensus (more than 50% of players must submit matching results).
Must be between 2 and 10.

EzRatingModel

Rating Model

GS2 uses Glicko-2 as its rating algorithm. Glicko-2 has several parameters, but GS2-Matchmaking aggregates them into a single parameter, volatility, which represents the totality of the parameters. Volatility is a parameter that expresses the magnitude of change; the larger the value, the greater the change in the rating value.

TypeConditionRequiredDefaultValue LimitsDescription
namestring
~ 128 charsRating Model name
Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
metadatastring~ 128 charsMetadata
Arbitrary values can be set in the metadata.
Since they do not affect GS2’s behavior, they can be used to store information used in the game.
volatilityint1001 ~ 20000Rating Volatility
A Glicko-2 parameter that controls how much the rating value changes after each match.
Higher values cause larger rating fluctuations, making ratings adjust more quickly.
Lower values result in more stable ratings that change gradually. Defaults to 100.

EzSeasonModel

Season Model

Defines the season-specific settings for Season Matchmaking, including the period of persistent gatherings, maximum participant count, and tier integration settings. Managed by GS2-Schedule for period control, and can be linked with GS2-Experience for persistent gathering within the same tier as needed.

TypeConditionRequiredDefaultValue LimitsDescription
namestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
metadatastring~ 128 charsMetadata
Arbitrary values can be set in the metadata.
Since they do not affect GS2’s behavior, they can be used to store information used in the game.
maximumParticipantsint
2 ~ 1000Maximum Number of Participants
The maximum number of players that can join a single Season Gathering.
Once this limit is reached, the Season Gathering is considered full and no more players can join.
Must be between 2 and 1000.
experienceModelIdstring~ 1024 charsExperience Model GRN for Tier Management
The GRN of the GS2-Experience experience model used to determine player tiers.
The player’s rank within this experience model is used as their tier for matchmaking, ensuring players are grouped with others at a similar level.
If not specified, tier-based grouping is disabled and all players are matched together regardless of level.
challengePeriodEventIdstring
~ 1024 charsChallenge Period Event GRN
The GRN of the GS2-Schedule event that defines the active period for this season.
Season Gatherings can only be created and joined while this event is active.
When the event period ends, the season closes and new matchmaking is no longer possible.

EzPlayer

Player

Represents a player participating in matchmaking, containing their identity, attributes, role, and blacklist. When joining a Gathering, a Player object is created with the player’s attribute values, desired role, and a list of users they refuse to play with. The player’s attributes are validated against the Gathering’s attribute range conditions, and their deny list is cross-checked to prevent unwanted pairings.

TypeConditionRequiredDefaultValue LimitsDescription
userIdstring
~ 128 charsUser ID
attributesList<EzAttribute>[]0 ~ 5 itemsList of Attributes
The player’s named numeric attributes used for matchmaking condition evaluation.
Each attribute is checked against the Gathering’s AttributeRange conditions to determine eligibility.
The player’s own attribute values must also fall within any range conditions they set when creating a Gathering. Maximum 5 attributes.
roleNamestring“default”~ 128 charsRole Name
The role that this player wants to fill in the Gathering.
Defaults to “default” for general matchmaking without role distinctions.
For role-based matchmaking, specify the player’s specific role (e.g., “paladin”, “knight”) which is matched against role names and aliases in the Gathering’s capacity definitions.
denyUserIdsList<string>[]0 ~ 100 itemsDeny User IDs
A blacklist of user IDs that this player refuses to be matched with.
During matchmaking, if any player already in the Gathering appears in this list, the player cannot join that Gathering.
Conversely, if this player is in any existing participant’s deny list, joining is also blocked. Maximum 100 entries.

EzAttributeRange

Attribute Range

A condition that defines the acceptable range of a named attribute for joining a Gathering. When a player attempts to join, their attribute value with the matching name must fall within the specified min/max range. Used to create skill-based or level-based matchmaking filters.

TypeConditionRequiredDefaultValue LimitsDescription
namestring
~ 128 charsAttribute Name
The name of the attribute to apply this range condition to.
Must match the name of an attribute in the player’s attribute list for the condition to be evaluated.
minint00 ~ 2147483646Minimum Attribute Value
The minimum value of the attribute required to join the Gathering (inclusive).
Players whose attribute value is below this threshold cannot participate.
maxint00 ~ 2147483646Maximum Attribute Value
The maximum value of the attribute allowed to join the Gathering (inclusive).
Players whose attribute value exceeds this threshold cannot participate.

EzCapacityOfRole

Capacity of Role

Defines a recruitment slot within a Gathering for a specific role. Each role has a name, optional aliases, a maximum capacity, and a list of currently participating players. Role aliases allow flexible matching: e.g., a “tank” role with aliases “paladin” and “knight” lets players specifying either sub-role fill the tank slot. When all participants in every role reach their capacity, the Gathering’s matchmaking is complete.

TypeConditionRequiredDefaultValue LimitsDescription
roleNamestring“default”~ 128 charsRole Name
The name of the role for this recruitment slot.
Defaults to “default” for general matchmaking without role distinctions.
For role-based matchmaking (e.g., “tank”, “healer”, “attacker”), specify the role category name here.
roleAliasesList<string>[]0 ~ 9 itemsList of Role Name Aliases
Alternative role names that are accepted for this recruitment slot.
Players specifying any of these aliases as their role name will be matched into this slot.
Enables sub-role matching: e.g., “paladin” and “knight” aliases for a “tank” role. Maximum 9 aliases.
capacityint
1 ~ 256Role Capacity
The maximum number of players that can fill this role slot.
When the number of participants reaches this capacity, the role is considered full and no more players with this role can join.
Must be between 1 and 256.
participantsList<EzPlayer>[]0 ~ 1000 itemsList of Participant Players
The list of players currently occupying this role slot.
Players are added when they join the Gathering and removed when they leave.
Each player entry includes their user ID, attributes, role name, and blacklist. Uniqueness is enforced by user ID.

EzAttribute

Attribute

A named numeric attribute associated with a player for matchmaking purposes. Attributes are used in conjunction with AttributeRange conditions on Gatherings to filter which players can join. For example, a “level” attribute with value 50 would match a Gathering requiring level between 40 and 60. Each player can have up to 5 attributes.

TypeConditionRequiredDefaultValue LimitsDescription
namestring
~ 128 charsAttribute Name
Attribute-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
valueint00 ~ 2147483646Attribute Value
The numeric value of this attribute for the player.
This value is checked against the min/max range specified in the Gathering’s AttributeRange conditions during matchmaking.

EzGameResult

Game Result

Represents the result of a single player in a match, used for rating calculations via the Vote system. Each GameResult entry pairs a user ID with their rank (finishing position) in the match. Lower rank values indicate better performance (1st place = rank 1). Players with the same rank are treated as a draw.

TypeConditionRequiredDefaultValue LimitsDescription
rankint
0 ~ 2147483646Rank
The player’s finishing position in the match. 1 is the highest rank (winner).
Used by the Glicko-2 algorithm to calculate rating changes: higher-ranked players gain rating while lower-ranked players lose rating.
Players with equal ranks are treated as draws.
userIdstring
~ 128 charsUser ID

EzSignedBallot

Signed Ballot

A ballot paper with a digital signature that verifies its authenticity. The server issues signed ballots to players after matchmaking completes, ensuring that only legitimate participants can submit match results. The signature is verified when the ballot is submitted to the Vote API, preventing tampering with match context (rating name, gathering name, number of players).

TypeConditionRequiredDefaultValue LimitsDescription
bodystring
~ 1024 charsBallot Body
The serialized ballot data that is the target of the digital signature.
Contains the ballot context (user ID, rating name, gathering name, number of players) in a format that can be verified against the signature.
signaturestring
~ 256 charsSignature
The digital signature used to verify the authenticity and integrity of the ballot body.
Generated by the server using a GS2-Key encryption key, and verified when the ballot is submitted to prevent forgery or tampering.

EzTimeSpan

Time Span

Represents a duration of time composed of days, hours, and minutes. Used to specify relative time offsets, such as the expiration time of a Gathering from the current time. The total duration is calculated by combining all three components.

TypeConditionRequiredDefaultValue LimitsDescription
daysint00 ~ 365Days
The number of days in the time span. Maximum 365 days. Defaults to 0.
hoursint00 ~ 24Hours
The number of hours in the time span. Maximum 24 hours. Defaults to 0.
minutesint00 ~ 60Minutes
The number of minutes in the time span. Maximum 60 minutes. Defaults to 0.

Methods

cancelMatchmaking

Cancel matchmaking and leave the Gathering

Removes the player from the Gathering they are currently in and stops matchmaking. Use this when the player taps a “Cancel” button on the matchmaking waiting screen.

Note: If matchmaking completes at the same moment the player tries to cancel, a NotFoundException (404 error) is returned because the Gathering no longer exists. Handle this case in your game — it means the match was found successfully and the player should proceed to the game instead.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
gameSessionGameSession
GameSession

Result

TypeDescription
itemEzGatheringCanceled Gathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var result = await domain.CancelMatchmakingAsync(
    );
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var future = domain.CancelMatchmakingFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    const auto Future = Domain->CancelMatchmaking(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

createGathering

Create a new room (Gathering) for matchmaking

Creates a matchmaking room and starts waiting for other players to join. You define the recruitment conditions when creating a Gathering — for example, “looking for 1 attacker and 1 healer, player level must be between 10 and 20”.

Key settings:

  • capacityOfRoles: Define the roles and how many players you need for each (e.g., 2 DPS + 1 Tank + 1 Healer).
  • attributeRanges: Set conditions for who can join based on player attributes like level or rank.
  • allowUserIds: Restrict the Gathering to specific players (useful for friend-only or invite-only matchmaking).
  • expiresAt: Set an expiration time for the Gathering. This is recommended — without it, old Gatherings may remain even after the player has left the game. If using expiration, prompt the player to recreate the Gathering when it expires.

The player’s own user ID in the Player parameter can be omitted.

After creating a Gathering, other players can find and join it by calling DoMatchmaking. When all role slots are filled, matchmaking completes and a notification is sent to all participants.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
playerEzPlayer
Own player information
attributeRangesList<EzAttributeRange>[]0 ~ 5 itemsRecruitment Requirements
A list of attribute range conditions that players must satisfy to join this Gathering.
Each entry specifies a named attribute and its acceptable min/max range.
A player’s own attribute values must fall within these ranges to participate. Maximum 5 conditions.
capacityOfRolesList<EzCapacityOfRole>[]1 ~ 5 itemsList of Role Capacities
Defines the recruitment slots for this Gathering.
Each entry specifies a role name, its aliases, and the maximum number of players that can fill that role.
When all role slots reach their capacity, matchmaking is considered complete. At least 1, maximum 5 roles.
allowUserIdsList<string>[]0 ~ 100 itemsAllowed User IDs
A whitelist of user IDs that are permitted to join this Gathering.
When specified, only the listed users can participate in matchmaking for this Gathering.
Useful for friend-only or invitation-based matchmaking scenarios. Maximum 100 entries.
expiresAtlongGathering Expiration Time
The time at which this Gathering automatically expires and is deleted.
If matchmaking does not complete before this time, the Gathering is cleaned up.
When not specified, the Gathering persists until matchmaking completes or it is manually deleted.
expiresAtTimeSpanEzTimeSpanTime to expiration

Result

TypeDescription
itemEzGatheringCreated Gathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var result = await domain.CreateGatheringAsync(
        player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer {
            Attributes = new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttribute> {
                new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute {
                    Name = "stage",
                    Value = 1,
                },
                new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute {
                    Name = "level",
                    Value = 10,
                },
            },
        },
        attributeRanges: new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "stage",
                Min = 1,
                Max = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "level",
                Min = 0,
                Max = 10,
            },
        },
        capacityOfRoles: new List<Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole {
                RoleName = "default",
                Capacity = 4,
            },
        },
        allowUserIds: null,
        expiresAt: null,
        expiresAtTimeSpan: null
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var future = domain.CreateGatheringFuture(
        player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer {
            Attributes = new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttribute> {
                new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute {
                    Name = "stage",
                    Value = 1,
                },
                new Gs2.Unity.Gs2Matchmaking.Model.EzAttribute {
                    Name = "level",
                    Value = 10,
                },
            },
        },
        attributeRanges: new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "stage",
                Min = 1,
                Max = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "level",
                Min = 0,
                Max = 10,
            },
        },
        capacityOfRoles: new List<Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzCapacityOfRole {
                RoleName = "default",
                Capacity = 4,
            },
        },
        allowUserIds: null,
        expiresAt: null,
        expiresAtTimeSpan: null
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto Future = Domain->CreateGathering(
        MakeShared<Gs2::UE5::Matchmaking::Model::FEzPlayer>()
            ->WithAttributes([]
            {
                auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzAttribute>>>();
                v->Add(
                    MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttribute>()
                    ->WithName(TOptional<FString>("stage"))
                    ->WithValue(TOptional<int32>(1)));
                v->Add(
                    MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttribute>()
                    ->WithName(TOptional<FString>("level"))
                    ->WithValue(TOptional<int32>(10)));
                return v;
            }())
        ), // player
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>()
                ->WithName(TOptional<FString>("stage"))
                ->WithMin(TOptional<int32>(1))
                ->WithMax(TOptional<int32>(1)));
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>()
                ->WithName(TOptional<FString>("level"))
                ->WithMin(TOptional<int32>(0))
                ->WithMax(TOptional<int32>(10)));
            return v;
        }(), // attributeRanges
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzCapacityOfRole>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzCapacityOfRole>()
                ->WithRoleName(TOptional<FString>("default"))
                ->WithCapacity(TOptional<int32>(4)));
            return v;
        }() // capacityOfRoles
        // allowUserIds
        // expiresAt
        // expiresAtTimeSpan
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

doMatchmaking

Search for an available Gathering and join it

Searches existing Gatherings for one that matches the player’s attributes and has open slots, then joins it automatically. This is the main API for players who want to join a match rather than create one.

The search takes a limited amount of time per call. If no suitable Gathering is found yet, a matchmakingContextToken is returned. Pass this token in the next call to resume the search from where it left off — keep calling in a loop until a match is found.

When all Gatherings have been searched and none are available, both the Gathering and the token will be null. In this case, you should create a new Gathering with CreateGathering instead.

Typical matchmaking flow:

  1. Call DoMatchmaking in a loop, passing the token each time
  2. If a Gathering is returned → matchmaking succeeded, proceed to the game
  3. If both Gathering and token are null → no matches found, create a new Gathering

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
playerEzPlayer
Own player information
matchmakingContextTokenstring~ 5120 charsUsed to resume search Token that holds matchmaking state

Result

TypeDescription
itemEzGatheringParticipated Gatherings
matchmakingContextTokenstringToken that preserves matchmaking status

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.DoMatchmakingAsync(
        player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer() {
            UserId = "user-0001",
            Attributes = new List<Gs2.Unity.Gs2MatchmakingEzAttribute> {
                new Gs2.Unity.Gs2MatchmakingEzAttribute() {
                    Name = "attr1",
                    Value = 1,
                },
                new Gs2.Unity.Gs2MatchmakingEzAttribute() {
                    Name = "attr2",
                    Value = 1,
                },
            }
        }
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.DoMatchmaking(
        player: new Gs2.Unity.Gs2Matchmaking.Model.EzPlayer() {
            UserId = "user-0001",
            Attributes = new List<Gs2.Unity.Gs2MatchmakingEzAttribute> {
                new Gs2.Unity.Gs2MatchmakingEzAttribute() {
                    Name = "attr1",
                    Value = 1,
                },
                new Gs2.Unity.Gs2MatchmakingEzAttribute() {
                    Name = "attr2",
                    Value = 1,
                },
            }
        }
    );

    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->DoMatchmaking(
        MakeShared<Gs2::UE5::Matchmaking::Model::FEzPlayer>()
            ->WithUserId(TOptional<FString>("user-0001"))
            ->WithAttributes([]
            {
                const auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzAttribute>>>();
                v->Add( MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttribute>()
                    ->WithName(TOptional<FString>("attr1"))
                    ->WithValue(TOptional<int32>(1))
                );
                v->Add( MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttribute>()
                    ->WithName(TOptional<FString>("attr2"))
                    ->WithValue(TOptional<int32>(1))
                );
                return v;
            }() // player
    );
    TArray<Gs2::UE5::Matchmaking::Model::FEzGatheringPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

earlyCompleteMatchmaking

Complete matchmaking early without a full party

Ends matchmaking before all role slots are filled. This is useful when you want to allow the game to start with fewer players than originally requested — for example, starting a 4-player co-op dungeon with only 3 players.

Only the player who created the Gathering can call this API. After calling, matchmaking is considered complete and a completion notification is sent to all participants.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
gameSessionGameSession
GameSession

Result

TypeDescription
itemEzGatheringCanceled Gathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var result = await domain.EarlyCompleteMatchmakingAsync(
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var future = domain.EarlyCompleteMatchmakingFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    const auto Future = Domain->EarlyCompleteMatchmaking(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

getGathering

Get the current state of a Gathering

Retrieves the latest information about a specific Gathering, including its participants, recruitment conditions, and role capacities. Use this to display a waiting room screen — for example, “2/4 players joined, looking for: 1 Tank, 1 Healer”.

You can also use this to check if matchmaking has completed by verifying that all role slots are filled.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.

Result

TypeDescription
itemEzGatheringGathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FGathering> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

ping

Send a keep-alive signal while waiting for matchmaking

Notifies the server that the player is still actively waiting for matchmaking. Call this periodically while the player is on the matchmaking waiting screen.

This helps the system know which players are still online and waiting. If the namespace has a timeout configured, players who don’t send a ping within the timeout period may be automatically removed from the Gathering.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.

Result

TypeDescription
itemEzGatheringGathering updated

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var result = await domain.PingAsync(
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var future = domain.PingFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    const auto Future = Domain->Ping(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

updateGathering

Update the recruitment conditions of a Gathering

Changes the attribute range conditions of an existing Gathering that is still waiting for players. For example, if no players are joining with the condition “level 15-20”, you can broaden it to “level 10-25” to increase the pool of eligible players.

Only the attribute ranges can be changed — role capacities and allowed user IDs cannot be modified after creation.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
gameSessionGameSession
GameSession
attributeRangesList<EzAttributeRange>[]0 ~ 5 itemsRecruitment Requirements
A list of attribute range conditions that players must satisfy to join this Gathering.
Each entry specifies a named attribute and its acceptable min/max range.
A player’s own attribute values must fall within these ranges to participate. Maximum 5 conditions.

Result

TypeDescription
itemEzGatheringGathering updated

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var result = await domain.UpdateGatheringAsync(
        attributeRanges: new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "stage",
                Min = 1,
                Max = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "level",
                Min = 0,
                Max = 50,
            },
        }
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Gathering(
        gatheringName: "gathering-0001"
    );
    var future = domain.UpdateGatheringFuture(
        attributeRanges: new List<Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "stage",
                Min = 1,
                Max = 1,
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzAttributeRange {
                Name = "level",
                Min = 0,
                Max = 50,
            },
        }
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Gathering(
        "gathering-0001" // gatheringName
    );
    const auto Future = Domain->UpdateGathering(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>()
                ->WithName(TOptional<FString>("stage"))
                ->WithMin(TOptional<int32>(1))
                ->WithMax(TOptional<int32>(1)));
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzAttributeRange>()
                ->WithName(TOptional<FString>("level"))
                ->WithMin(TOptional<int32>(0))
                ->WithMax(TOptional<int32>(50)));
            return v;
        }() // attributeRanges
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

getRatingModel

Get the details of a specific rating configuration

Retrieves a single rating model by name. Use this to display the rating system’s settings — including the initial rating value and volatility parameter.

Higher volatility means ratings change more dramatically after each match (good for quickly calibrating new players), while lower volatility leads to more stable, gradual rating changes.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
ratingNamestring
~ 128 charsRating Model name
Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemEzRatingModelRating Model

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->RatingModel(
        "mode1" // ratingName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->RatingModel(
        "mode1" // ratingName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FRatingModel> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

listRatingModels

Get a list of all rating configurations

Retrieves all rating models configured in the namespace. Each rating model defines the parameters for a player skill rating system — for example, you might have separate ratings for “Ranked Battle”, “Arena”, and “Tournament”.

GS2 uses the Glicko-2 algorithm for rating calculations. Each model specifies the initial rating value (default: 1500) and volatility (how quickly ratings change after each match).

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemsList<EzRatingModel>List of Rating Model

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.RatingModelsAsync(
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.RatingModels(
    );
    List<EzRatingModel> items = new List<EzRatingModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->RatingModels(
    );
    TArray<Gs2::UE5::Matchmaking::Model::FEzRatingModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeRatingModels(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeRatingModels(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeRatingModels(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeRatingModels(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeRatingModels(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeRatingModels(CallbackId);

getRating

Get the player’s rating score for a specific category

Retrieves the player’s current rating value for the specified rating name. Use this to display a single rating — for example, showing “Your Ranked Battle Rating: 1823” on a match result screen or lobby.

The rating value goes up when the player wins and down when they lose, with the amount of change depending on the opponent’s rating and the volatility setting.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
ratingNamestring
~ 128 charsRating name
Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemEzRatingRating

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Rating(
        "rating-0001" // ratingName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Rating(
        "rating-0001" // ratingName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FRating> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

listRatings

Get the player’s rating scores across all rating categories

Retrieves all of the player’s current rating values. If your game has multiple rating categories (e.g., “Ranked Battle” and “Arena”), this returns the player’s score for each one.

Use this to build a profile or stats screen — for example, “Ranked Battle: 1823, Arena: 1547”. A player’s rating is automatically created when they first participate in a rated match, starting at the initial value (typically 1500).

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
pageTokenstring~ 1024 charsToken specifying the position from which to start acquiring data
limitint301 ~ 1000Number of data acquired

Result

TypeDescription
itemsList<EzRating>List of Rating
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.RatingsAsync(
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Ratings(
    );
    List<EzRating> items = new List<EzRating>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Ratings(
    );
    TArray<Gs2::UE5::Matchmaking::Model::FEzRatingPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeRatings(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeRatings(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeRatings(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeRatings(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeRatings(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeRatings(CallbackId);

createVote

Create a signed ballot for reporting match results

Generates a ballot (voting paper) for the player to use when reporting the outcome of a match. After a rated match ends, each player needs to report who won and who lost. This API creates a tamper-proof ballot that includes the player’s identity information and a cryptographic signature.

How the match result reporting flow works:

  1. The match ends and each player’s game client calls CreateVote to get their signed ballot
  2. Each player submits their ballot along with the match results using the Vote API
  3. The server collects all votes and determines the final result by majority vote
  4. Player ratings are updated based on the confirmed result

Parameters:

  • ratingName: The name of the rating category this match belongs to (e.g., “ranked_battle”)
  • gatheringName: The name of the Gathering (matchmaking room) where this match took place
  • numberOfPlayer: The total number of players in the match (2-10)
  • keyId: The encryption key used for signing the ballot (use the default key if you haven’t set up a custom one)

The returned ballot body and signature are needed for the Vote or VoteMultiple API call.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
ratingNamestring
~ 128 charsRating Model name
Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestring
UUID~ 128 charsGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
gameSessionGameSession
GameSession
numberOfPlayerint
2 ~ 10Number of participants
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024 charsEncryption Key GRN

Result

TypeDescription
itemEzBallotBallot
bodystringData to be signed
signaturestringSignature

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Ballot(
        ratingName: "rating-0001",
        gatheringName: "gathering-0001",
        numberOfPlayer: 4,
        keyId: "key-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Ballot(
        ratingName: "rating-0001",
        gatheringName: "gathering-0001",
        numberOfPlayer: 4,
        keyId: "key-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Ballot(
        "rating-0001", // ratingName
        "gathering-0001", // gatheringName
        4, // numberOfPlayer
        "key-0001" // keyId
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Ballot(
        ratingName: "rating-0001",
        gatheringName: "gathering-0001",
        numberOfPlayer: 4,
        keyId: "key-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Ballot(
        ratingName: "rating-0001",
        gatheringName: "gathering-0001",
        numberOfPlayer: 4,
        keyId: "key-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Ballot(
        "rating-0001", // ratingName
        "gathering-0001", // gatheringName
        4, // numberOfPlayer
        "key-0001" // keyId
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FBallot> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

vote

Submit your match result vote

Each player calls this API individually to report who won and who lost after a match. Pass the ballot body and signature obtained from CreateVote, along with the game results (a list of each player’s rank or win/loss).

How voting works:

  • After the first player votes, there is a 5-minute window for all other players to vote
  • If all players vote before the 5 minutes, the result is confirmed immediately
  • If some players don’t vote within 5 minutes, the result is decided by majority vote based on the votes received so far
  • If votes are tied (e.g., 2 say “Player A won” and 2 say “Player B won”), the result is discarded and ratings are not updated (this behavior can be customized with a script)

This is the simplest approach — each player votes independently. The downside is that results may take up to 5 minutes to be reflected.

For instant results, use VoteMultiple instead — the winning player collects all ballots and submits them together.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
ballotBodystring
~ 1024 charsData for ballot signature targets
ballotSignaturestring
~ 256 charsSignature
gameResultsList<EzGameResult>0 ~ 10 itemsList of Results
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024 charsEncryption Key GRN

Result

TypeDescription
itemEzBallotBallot

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var result = await domain.VoteAsync(
        ballotBody: "ballotBody...",
        ballotSignature: "ballotSignature...",
        gameResults: new List<Gs2.Unity.Gs2Matchmaking.Model.EzGameResult> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 1,
                UserId = "user-0001",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0002",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0003",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 3,
                UserId = "user-0004",
            },
        },
        keyId: "key-0001"
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var future = domain.VoteFuture(
        ballotBody: "ballotBody...",
        ballotSignature: "ballotSignature...",
        gameResults: new List<Gs2.Unity.Gs2Matchmaking.Model.EzGameResult> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 1,
                UserId = "user-0001",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0002",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0003",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 3,
                UserId = "user-0004",
            },
        },
        keyId: "key-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto Future = Domain->Vote(
        "ballotBody...", // ballotBody
        "ballotSignature...", // ballotSignature
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzGameResult>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(1))
                ->WithUserId(TOptional<FString>("user-0001"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(2))
                ->WithUserId(TOptional<FString>("user-0002"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(2))
                ->WithUserId(TOptional<FString>("user-0003"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(3))
                ->WithUserId(TOptional<FString>("user-0004"))
            );
            return v;
        }(), // gameResults
        "key-0001" // keyId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

voteMultiple

Collect all ballots and submit match results at once for instant confirmation

Instead of each player voting individually (which can take up to 5 minutes), the winning player collects everyone’s signed ballots and submits them all together. This confirms the result immediately.

Recommended flow:

  1. The match ends — each player calls CreateVote to get their signed ballot
  2. Each player sends their ballot (body + signature) to the winning player via your game’s communication channel (e.g., the game server or peer-to-peer)
  3. The winning player calls VoteMultiple with all collected ballots and the game results
  4. The result is confirmed instantly and ratings are updated

Why the winning player should collect ballots:

  • The losing side has no reason to lie about winning (they’d gain nothing), but they might refuse to hand over their ballot
  • Even if the losing side doesn’t cooperate, as long as you have a majority of ballots (more than half), the result will be accepted
  • For example, in a 2v2 match, if both winners submit their ballots, that’s 2 out of 4 — enough for a majority

This approach is more complex to implement but gives instant results, which is better for the player experience.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
signedBallotsList<EzSignedBallot>0 ~ 10 itemsList of Ballot with signatures
gameResultsList<EzGameResult>0 ~ 10 itemsList of Results
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024 charsEncryption Key GRN

Result

TypeDescription
itemEzBallotBallot

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var result = await domain.VoteMultipleAsync(
        signedBallots: new List<Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
        },
        gameResults: new List<Gs2.Unity.Gs2Matchmaking.Model.EzGameResult> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 1,
                UserId = "user-0001",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0002",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0003",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 3,
                UserId = "user-0004",
            },
        },
        keyId: "key-0001"
    );
    var item = await result.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var future = domain.VoteMultipleFuture(
        signedBallots: new List<Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzSignedBallot() {
                Body = "aaa",
                Signature = "bbb",
            },
        },
        gameResults: new List<Gs2.Unity.Gs2Matchmaking.Model.EzGameResult> {
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 1,
                UserId = "user-0001",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0002",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 2,
                UserId = "user-0003",
            },
            new Gs2.Unity.Gs2Matchmaking.Model.EzGameResult() {
                Rank = 3,
                UserId = "user-0004",
            },
        },
        keyId: "key-0001"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto Future = Domain->VoteMultiple(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzSignedBallot>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzSignedBallot>()
                ->WithBody(TOptional<FString>("aaa"))
                ->WithSignature(TOptional<FString>("bbb"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzSignedBallot>()
                ->WithBody(TOptional<FString>("aaa"))
                ->WithSignature(TOptional<FString>("bbb"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzSignedBallot>()
                ->WithBody(TOptional<FString>("aaa"))
                ->WithSignature(TOptional<FString>("bbb"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzSignedBallot>()
                ->WithBody(TOptional<FString>("aaa"))
                ->WithSignature(TOptional<FString>("bbb"))
            );
            return v;
        }(), // signedBallots
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::Matchmaking::Model::FEzGameResult>>>();
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(1))
                ->WithUserId(TOptional<FString>("user-0001"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(2))
                ->WithUserId(TOptional<FString>("user-0002"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(2))
                ->WithUserId(TOptional<FString>("user-0003"))
            );
            v->Add(
                MakeShared<Gs2::UE5::Matchmaking::Model::FEzGameResult>()
                ->WithRank(TOptional<int32>(3))
                ->WithUserId(TOptional<FString>("user-0004"))
            );
            return v;
        }(), // gameResults
        "key-0001" // keyId
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

getJoinedSeasonGathering

Get the Season Gathering the player joined for a specific season

Retrieves the Season Gathering that the player belongs to for the specified season number. Use this to check which match group the player is in for the current season — for example, to resume showing the match lobby after the player restarts the app.

If the player has not joined any Season Gathering for the specified season, or if the Gathering no longer exists, the information will not be returned. In that case, the player should start a new matchmaking search with DoSeasonMatchmaking.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonlong0 ~ 9223372036854775805Season
gameSessionGameSession
GameSession

Result

TypeDescription
itemEzJoinedSeasonGatheringJoinedSeasonGathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    )->JoinedSeasonGathering(
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    )->JoinedSeasonGathering(
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FJoinedSeasonGathering> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

listJoinedSeasonGatherings

Get a list of Season Gatherings the player has joined

Retrieves all the Season Gatherings that the player is currently a member of. Use this to show a match history or active matches screen — for example, listing all the ranked matches the player is participating in or has participated in this season.

You can filter by season name to show only matches for a specific ranked mode (e.g., only “Ranked 1v1” matches).

This is useful for:

  • Showing the player’s current active matches when they open the game
  • Building a match history screen
  • Checking if the player is already in a match before starting a new matchmaking search

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonNamestring~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession

Result

TypeDescription
itemsList<EzJoinedSeasonGathering>List of Season Gathering
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    var items = await domain.JoinedSeasonGatheringsAsync(
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    var it = domain.JoinedSeasonGatherings(
    );
    List<EzJoinedSeasonGathering> items = new List<EzJoinedSeasonGathering>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    );
    const auto It = Domain->JoinedSeasonGatherings(
    );
    TArray<Gs2::UE5::Matchmaking::Model::FEzJoinedSeasonGatheringPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    
    // Start event handling
    var callbackId = domain.SubscribeJoinedSeasonGatherings(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeJoinedSeasonGatherings(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    
    // Start event handling
    var callbackId = domain.SubscribeJoinedSeasonGatherings(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeJoinedSeasonGatherings(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeJoinedSeasonGatherings(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeJoinedSeasonGatherings(CallbackId);

doSeasonMatchmaking

Search for an available season match and join it

Searches for a Season Gathering (a persistent matchmaking group) in the player’s tier that has open slots, and joins it automatically. The player’s tier is determined by their experience level in the linked GS2-Experience model — so players of similar skill are matched together.

This works similarly to regular DoMatchmaking, but with tier-based grouping:

  • The search takes a limited amount of time per call. If no match is found yet, a matchmakingContextToken is returned.
  • Pass this token in your next call to resume the search from where it left off.
  • Keep calling in a loop until a match is found.

When all Season Gatherings have been searched and none have open slots, both the Season Gathering and token are returned as null. Unlike regular matchmaking where you would create a new Gathering yourself, in season matchmaking a new Season Gathering is created automatically by the system when needed.

Typical season matchmaking flow:

  1. Call DoSeasonMatchmaking in a loop, passing the token each time
  2. If a Season Gathering is returned → match found, proceed to the game
  3. If both are null → no available matches right now, show a “searching” screen and retry after a short delay

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
matchmakingContextTokenstring~ 5120 charsUsed to resume search Token that holds matchmaking state

Result

TypeDescription
itemEzSeasonGatheringParticipated Season Gatherings
matchmakingContextTokenstringToken that preserves matchmaking status

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    var items = await domain.DoSeasonMatchmakingAsync(
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );
    var it = domain.DoSeasonMatchmaking(
    );

    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    );
    const auto It = Domain->DoSeasonMatchmaking(
    );

    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }

getSeasonGathering

Get the current state of a Season Gathering

Retrieves the details of a specific Season Gathering, including the list of participants and which tier it belongs to. Use this to display the match lobby or waiting room for a season match — for example, “Gold Tier Match #42: 3/4 players joined”.

You need to specify the season number, tier, and gathering name to identify the exact Season Gathering. This information is returned when you successfully join a Season Gathering via DoSeasonMatchmaking.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonlong0 ~ 9223372036854775805Season
tierlong
0 ~ 9223372036854775805Tier
The tier level used to group players of similar rank together.
Determined by the player’s rank in the GS2-Experience model specified in the SeasonModel.
Players are only matched with others in the same tier, ensuring fair competition.
seasonGatheringNamestring
UUID~ 128 charsSeason Gathering Name
Season Gathering-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemEzSeasonGatheringSeasonGathering

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).SeasonGathering(
        tier: 0,
        seasonGatheringName: "gathering-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).SeasonGathering(
        tier: 0,
        seasonGatheringName: "gathering-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->Season(
        "season-0001", // seasonName
        0 // season
    )->SeasonGathering(
        0, // tier
        "gathering-0001" // seasonGatheringName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).SeasonGathering(
        tier: 0,
        seasonGatheringName: "gathering-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).SeasonGathering(
        tier: 0,
        seasonGatheringName: "gathering-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->Season(
        "season-0001", // seasonName
        0 // season
    )->SeasonGathering(
        0, // tier
        "gathering-0001" // seasonGatheringName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FSeasonGathering> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

getSeasonModel

Get the details of a specific season matchmaking configuration

Retrieves a single season model by name. Use this to display the rules and settings for a specific ranked mode — for example, showing “Ranked 1v1: Max 2 players, Tier based on Arena Experience” on a mode selection screen.

The response includes:

  • maximumParticipants: How many players can be in a single match
  • experienceModelId: Which GS2-Experience model is used to determine player tiers. The player’s experience level is mapped to a tier, and matchmaking only pairs players within the same tier.
  • challengePeriodEventId: If set, players can only participate in ranked matches during the specified time window (e.g., weekends only, or 7PM-10PM daily)

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
seasonNamestring
~ 128 charsSeason Model name
Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemEzSeasonModelSeason Model

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->SeasonModel(
        "season-0001" // seasonName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->SeasonModel(
        "season-0001" // seasonName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FSeasonModel> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

listSeasonModels

Get a list of all season matchmaking configurations

Retrieves all season models defined in the namespace. Season matchmaking is designed for competitive games with ranked seasons — like “Season 1”, “Season 2”, etc. — where players are grouped into tiers based on their skill level.

Unlike regular Gathering-based matchmaking (which creates temporary rooms), season matchmaking uses persistent groups that last for the entire season. Players in the same tier are matched together, ensuring fair competition.

Each season model defines:

  • Maximum number of participants per match
  • The experience model used to calculate player tiers (integrates with GS2-Experience to determine skill brackets like Bronze, Silver, Gold)
  • An optional challenge period event (integrates with GS2-Schedule to limit when matches can be played)

Use this to display a list of available ranked modes — for example, “Ranked 1v1” and “Ranked 3v3”.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).

Result

TypeDescription
itemsList<EzSeasonModel>List of Season Model

Implementation Example

    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var items = await domain.SeasonModelsAsync(
    ).ToListAsync();
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    var it = domain.SeasonModels(
    );
    List<EzSeasonModel> items = new List<EzSeasonModel>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    const auto It = Domain->SeasonModels(
    );
    TArray<Gs2::UE5::Matchmaking::Model::FEzSeasonModelPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeSeasonModels(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeSeasonModels(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );
    
    // Start event handling
    var callbackId = domain.SubscribeSeasonModels(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeSeasonModels(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeSeasonModels(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeSeasonModels(CallbackId);

Event Handler

OnJoinNotification

Push notification used when a new participant joins the Gathering

NameTypeDescription
namespaceNamestringNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestringGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
joinUserIdstringUser ID

Implementation Example

    gs2.Matchmaking.OnJoinNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
        var joinUserId = notification.JoinUserId;
    };
    gs2.Matchmaking.OnJoinNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
        var joinUserId = notification.JoinUserId;
    };
    Gs2->Matchmaking->OnJoinNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto GatheringName = Notification->GatheringNameValue;
        const auto JoinUserId = Notification->JoinUserIdValue;
    });

OnLeaveNotification

Push notification used when a participant leaves the Gathering

NameTypeDescription
namespaceNamestringNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestringGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.
leaveUserIdstringUser ID

Implementation Example

    gs2.Matchmaking.OnLeaveNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
        var leaveUserId = notification.LeaveUserId;
    };
    gs2.Matchmaking.OnLeaveNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
        var leaveUserId = notification.LeaveUserId;
    };
    Gs2->Matchmaking->OnLeaveNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto GatheringName = Notification->GatheringNameValue;
        const auto LeaveUserId = Notification->LeaveUserIdValue;
    });

OnCompleteNotification

Push notification used when matchmaking is established

NameTypeDescription
namespaceNamestringNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gatheringNamestringGathering name
Maintains a unique name for each Gathering.
Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering.

Implementation Example

    gs2.Matchmaking.OnCompleteNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
    };
    gs2.Matchmaking.OnCompleteNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var gatheringName = notification.GatheringName;
    };
    Gs2->Matchmaking->OnCompleteNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto GatheringName = Notification->GatheringNameValue;
    });

OnChangeRatingNotification

Push notification used when rating values change

NameTypeDescription
namespaceNamestringNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
ratingNamestringRating name
Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
userIdstringUser ID
rateValuefloatRate Value
The player’s current rating score calculated by the Glicko-2 algorithm.
Defaults to the initial value defined in the RatingModel (typically 1500.0).
The value increases or decreases based on match results and the relative strength of opponents.

Implementation Example

    gs2.Matchmaking.OnChangeRatingNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var ratingName = notification.RatingName;
        var userId = notification.UserId;
        var rateValue = notification.RateValue;
    };
    gs2.Matchmaking.OnChangeRatingNotification += notification =>
    {
        var namespaceName = notification.NamespaceName;
        var ratingName = notification.RatingName;
        var userId = notification.UserId;
        var rateValue = notification.RateValue;
    };
    Gs2->Matchmaking->OnChangeRatingNotification().AddLambda([](const auto Notification)
    {
        const auto NamespaceName = Notification->NamespaceNameValue;
        const auto RatingName = Notification->RatingNameValue;
        const auto UserId = Notification->UserIdValue;
        const auto RateValue = Notification->RateValueValue;
    });