GS2-Matchmaking SDK for Game Engine API Reference
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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| gatheringId | string | * | ~ 1024 chars | Gathering GRN * Set automatically by the server | ||
| name | string | ✓ | UUID | ~ 128 chars | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. | |
| attributeRanges | List<EzAttributeRange> | [] | 0 ~ 5 items | Recruitment 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. | ||
| capacityOfRoles | List<EzCapacityOfRole> | [] | 1 ~ 5 items | List 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. | ||
| allowUserIds | List<string> | [] | 0 ~ 100 items | Allowed 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. | ||
| metadata | string | ~ 1024 chars | Metadata 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. | |||
| expiresAt | long | Gathering 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. | ||||
| createdAt | long | * | Now | Datetime of creation Unix time, milliseconds * Set automatically by the server | ||
| updatedAt | long | * | Now | Datetime 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| ratingId | string | * | ~ 1024 chars | Rating GRN * Set automatically by the server | ||
| name | string | ✓ | ~ 128 chars | Rating name Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| userId | string | ✓ | ~ 128 chars | User ID | ||
| rateValue | float | 1500.0 | 0 ~ 65535.0 | Rate 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. | ||
| createdAt | long | * | Now | Datetime of creation Unix time, milliseconds * Set automatically by the server | ||
| updatedAt | long | * | Now | Datetime 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| season | long | ✓ | 0 ~ 9223372036854775805 | Season | ||
| tier | long | ✓ | 0 ~ 9223372036854775805 | Tier 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. | ||
| seasonGatheringName | string | ✓ | ~ 128 chars | Season 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| seasonGatheringId | string | * | ~ 1024 chars | Season Gathering GRN * Set automatically by the server | ||
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| season | long | ✓ | 0 ~ 9223372036854775805 | Season | ||
| tier | long | ✓ | 0 ~ 9223372036854775805 | Tier 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. | ||
| name | string | ✓ | UUID | ~ 128 chars | Season Gathering Name Season Gathering-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | |
| participants | List<string> | [] | 0 ~ 1000 items | List 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| userId | string | ✓ | ~ 128 chars | User ID | ||
| ratingName | string | ✓ | ~ 128 chars | Rating 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. | ||
| gatheringName | string | ✓ | ~ 128 chars | Gathering 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. | ||
| numberOfPlayer | int | ✓ | 2 ~ 10 | Number 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Rating Model name Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| metadata | string | ~ 128 chars | Metadata 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. | |||
| volatility | int | 100 | 1 ~ 20000 | Rating 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| metadata | string | ~ 128 chars | Metadata 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. | |||
| maximumParticipants | int | ✓ | 2 ~ 1000 | Maximum 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. | ||
| experienceModelId | string | ~ 1024 chars | Experience 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. | |||
| challengePeriodEventId | string | ✓ | ~ 1024 chars | Challenge 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| userId | string | ✓ | ~ 128 chars | User ID | ||
| attributes | List<EzAttribute> | [] | 0 ~ 5 items | List 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. | ||
| roleName | string | “default” | ~ 128 chars | Role 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. | ||
| denyUserIds | List<string> | [] | 0 ~ 100 items | Deny 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Attribute 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. | ||
| min | int | 0 | 0 ~ 2147483646 | Minimum Attribute Value The minimum value of the attribute required to join the Gathering (inclusive). Players whose attribute value is below this threshold cannot participate. | ||
| max | int | 0 | 0 ~ 2147483646 | Maximum 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| roleName | string | “default” | ~ 128 chars | Role 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. | ||
| roleAliases | List<string> | [] | 0 ~ 9 items | List 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. | ||
| capacity | int | ✓ | 1 ~ 256 | Role 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. | ||
| participants | List<EzPlayer> | [] | 0 ~ 1000 items | List 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| name | string | ✓ | ~ 128 chars | Attribute Name Attribute-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| value | int | 0 | 0 ~ 2147483646 | Attribute 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| rank | int | ✓ | 0 ~ 2147483646 | Rank 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. | ||
| userId | string | ✓ | ~ 128 chars | User 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).
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| body | string | ✓ | ~ 1024 chars | Ballot 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. | ||
| signature | string | ✓ | ~ 256 chars | Signature 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.
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| days | int | 0 | 0 ~ 365 | Days The number of days in the time span. Maximum 365 days. Defaults to 0. | ||
| hours | int | 0 | 0 ~ 24 | Hours The number of hours in the time span. Maximum 24 hours. Defaults to 0. | ||
| minutes | int | 0 | 0 ~ 60 | Minutes 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. | |
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| item | EzGathering | Canceled 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| player | EzPlayer | ✓ | Own player information | |||
| attributeRanges | List<EzAttributeRange> | [] | 0 ~ 5 items | Recruitment 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. | ||
| capacityOfRoles | List<EzCapacityOfRole> | [] | 1 ~ 5 items | List 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. | ||
| allowUserIds | List<string> | [] | 0 ~ 100 items | Allowed 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. | ||
| expiresAt | long | Gathering 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. | ||||
| expiresAtTimeSpan | EzTimeSpan | Time to expiration |
Result
| Type | Description | |
|---|---|---|
| item | EzGathering | Created 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:
- Call DoMatchmaking in a loop, passing the token each time
- If a Gathering is returned → matchmaking succeeded, proceed to the game
- If both Gathering and token are null → no matches found, create a new Gathering
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| player | EzPlayer | ✓ | Own player information | |||
| matchmakingContextToken | string | ~ 5120 chars | Used to resume search Token that holds matchmaking state |
Result
| Type | Description | |
|---|---|---|
| item | EzGathering | Participated Gatherings |
| matchmakingContextToken | string | Token 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. | |
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| item | EzGathering | Canceled 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering 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
| Type | Description | |
|---|---|---|
| item | EzGathering | Gathering |
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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering 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
| Type | Description | |
|---|---|---|
| item | EzGathering | Gathering 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. | |
| gameSession | GameSession | ✓ | GameSession | |||
| attributeRanges | List<EzAttributeRange> | [] | 0 ~ 5 items | Recruitment 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
| Type | Description | |
|---|---|---|
| item | EzGathering | Gathering 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| ratingName | string | ✓ | ~ 128 chars | Rating Model name Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzRatingModel | Rating 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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| items | List<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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| ratingName | string | ✓ | ~ 128 chars | Rating name Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzRating | Rating |
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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| pageToken | string | ~ 1024 chars | Token specifying the position from which to start acquiring data | |||
| limit | int | 30 | 1 ~ 1000 | Number of data acquired |
Result
| Type | Description | |
|---|---|---|
| items | List<EzRating> | List of Rating |
| nextPageToken | string | Page 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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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:
- The match ends and each player’s game client calls CreateVote to get their signed ballot
- Each player submits their ballot along with the match results using the Vote API
- The server collects all votes and determines the final result by majority vote
- 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| ratingName | string | ✓ | ~ 128 chars | Rating Model name Rating Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gatheringName | string | ✓ | UUID | ~ 128 chars | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. | |
| gameSession | GameSession | ✓ | GameSession | |||
| numberOfPlayer | int | ✓ | 2 ~ 10 | Number of participants | ||
| keyId | string | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024 chars | Encryption Key GRN |
Result
| Type | Description | |
|---|---|---|
| item | EzBallot | Ballot |
| body | string | Data to be signed |
| signature | string | Signature |
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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| ballotBody | string | ✓ | ~ 1024 chars | Data for ballot signature targets | ||
| ballotSignature | string | ✓ | ~ 256 chars | Signature | ||
| gameResults | List<EzGameResult> | 0 ~ 10 items | List of Results | |||
| keyId | string | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024 chars | Encryption Key GRN |
Result
| Type | Description | |
|---|---|---|
| item | EzBallot | Ballot |
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:
- The match ends — each player calls CreateVote to get their signed ballot
- 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)
- The winning player calls VoteMultiple with all collected ballots and the game results
- 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| signedBallots | List<EzSignedBallot> | 0 ~ 10 items | List of Ballot with signatures | |||
| gameResults | List<EzGameResult> | 0 ~ 10 items | List of Results | |||
| keyId | string | “grn:gs2:{region}:{ownerId}:key:default:key:default” | ~ 1024 chars | Encryption Key GRN |
Result
| Type | Description | |
|---|---|---|
| item | EzBallot | Ballot |
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| season | long | 0 ~ 9223372036854775805 | Season | |||
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| item | EzJoinedSeasonGathering | JoinedSeasonGathering |
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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| seasonName | string | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | |||
| gameSession | GameSession | ✓ | GameSession |
Result
| Type | Description | |
|---|---|---|
| items | List<EzJoinedSeasonGathering> | List of Season Gathering |
| nextPageToken | string | Page 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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
matchmakingContextTokenis 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:
- Call DoSeasonMatchmaking in a loop, passing the token each time
- If a Season Gathering is returned → match found, proceed to the game
- If both are null → no available matches right now, show a “searching” screen and retry after a short delay
Request
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| gameSession | GameSession | ✓ | GameSession | |||
| matchmakingContextToken | string | ~ 5120 chars | Used to resume search Token that holds matchmaking state |
Result
| Type | Description | |
|---|---|---|
| item | EzSeasonGathering | Participated Season Gatherings |
| matchmakingContextToken | string | Token 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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| season | long | 0 ~ 9223372036854775805 | Season | |||
| tier | long | ✓ | 0 ~ 9223372036854775805 | Tier 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. | ||
| seasonGatheringName | string | ✓ | UUID | ~ 128 chars | Season Gathering Name Season Gathering-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzSeasonGathering | SeasonGathering |
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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). | ||
| seasonName | string | ✓ | ~ 128 chars | Season Model name Season Model-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| item | EzSeasonModel | Season 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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
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
| Type | Condition | Required | Default | Value Limits | Description | |
|---|---|---|---|---|---|---|
| namespaceName | string | ✓ | ~ 128 chars | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
Result
| Type | Description | |
|---|---|---|
| items | List<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);Warning
This event is triggered when the value stored in the SDK’s local cache changes.
The local cache is updated only when executing the SDK’s API, or by executing stamp sheets via GS2-Distributor with GS2-Gateway notification enabled, or by executing a GS2-JobQueue with GS2-Gateway notification enabled.
Therefore, callbacks will not be invoked if the value is changed in any other way.
Event Handler
OnJoinNotification
Push notification used when a new participant joins the Gathering
| Name | Type | Description |
|---|---|---|
| namespaceName | string | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| gatheringName | string | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. |
| joinUserId | string | User 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
| Name | Type | Description |
|---|---|---|
| namespaceName | string | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| gatheringName | string | Gathering name Maintains a unique name for each Gathering. Names are automatically generated in UUID (Universally Unique Identifier) format and used to identify each Gathering. |
| leaveUserId | string | User 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
| Name | Type | Description |
|---|---|---|
| namespaceName | string | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| gatheringName | string | Gathering 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
| Name | Type | Description |
|---|---|---|
| namespaceName | string | Namespace name Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| ratingName | string | Rating name Rating-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.). |
| userId | string | User ID |
| rateValue | float | Rate 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;
});