Documentation index for AI agents

GS2-Matchmaking SDK for Game Engine API 레퍼런스

게임 엔진용 GS2-Matchmaking SDK의 모델 사양과 API 레퍼런스

모델

EzGathering

개더링

매치메이킹에 의해 모인 게임 플레이어 그룹을 나타내는 엔티티입니다.
매치메이킹용 파라미터를 여러 개 가지고 있으며, 파라미터를 종합적으로 판단하여 플레이어를 그룹화합니다.
플레이어는 자신의 역할·속성값·거부 리스트(함께 플레이하고 싶지 않은 사용자)를 지정하여 개더링에 참가합니다.
참가 시에는 속성값 범위 조건, 역할의 정원, 화이트리스트 제한(allowUserIds)이 검증됩니다.
모든 역할 슬롯이 정원에 도달하면 개더링은 완성 상태가 되어 매치메이킹이 완료됩니다.
개더링 이름은 UUID 형식으로 자동 생성되며, 유효기간을 설정하여 자동 정리(클린업)하는 것도 가능합니다.

타입활성화 조건필수기본값값 제한설명
gatheringIdstring
~ 1024자개더링 GRN
※ 서버가 자동으로 설정
namestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
attributeRangesList<EzAttributeRange>[]0 ~ 5 items모집 조건
이 개더링에 참가하기 위해 플레이어가 충족해야 하는 속성 범위 조건의 목록입니다.
각 항목은 속성 이름과 허용되는 최소값·최대값 범위를 지정합니다.
플레이어 자신의 속성값이 이 범위 내에 있지 않으면 참가할 수 없습니다. 최대 5건.
capacityOfRolesList<EzCapacityOfRole>[]1 ~ 5 items모집 슬롯 목록
이 개더링의 모집 슬롯을 정의합니다.
각 항목은 역할 이름, 그 별칭, 그리고 해당 역할에 참가 가능한 최대 인원수를 지정합니다.
모든 역할 슬롯이 정원에 도달하면 매치메이킹이 완료됩니다. 최소 1건, 최대 5건.
allowUserIdsList<string>[]0 ~ 100 items참가 허용 사용자 ID 목록
이 게더링에 참가하는 것이 허용된 사용자 ID의 화이트리스트입니다.
지정한 경우, 목록에 포함된 사용자만 이 게더링의 매치메이킹에 참가할 수 있습니다.
친구 전용 매치메이킹이나 초대제 매치메이킹 시나리오에 유용합니다. 최대 100건.
metadatastring~ 1024자메타데이터
메타데이터에는 임의의 값을 설정할 수 있습니다.
이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다.
expiresAtlong게더링 유효 기간
이 게더링이 자동으로 만료되어 삭제되는 시각입니다.
이 시각까지 매치메이킹이 완료되지 않으면 게더링은 정리됩니다.
지정하지 않은 경우, 매치메이킹이 완료되거나 수동으로 삭제될 때까지 게더링이 유지됩니다.
createdAtlong
현재 시각생성일시
UNIX 시간·밀리초
※ 서버가 자동으로 설정
updatedAtlong
현재 시각최종 갱신일시
UNIX 시간·밀리초
※ 서버가 자동으로 설정

EzRating

레이팅

게임 플레이어별 현재 레이팅 값을 보유하는 엔티티입니다.
플레이어가 처음 레이팅이 적용된 매치메이킹에 참가했을 때 자동으로 생성됩니다.
레이팅은 Glicko-2 알고리즘을 사용하여 계산되며, 초기 레이트 값과 레이팅의 불확실성을 나타내는 Rating Deviation(rd)을 가집니다.
대전 횟수가 늘어남에 따라 레이트 값은 플레이어의 실제 실력에 수렴해 갑니다.

타입활성화 조건필수기본값값 제한설명
ratingIdstring
~ 1024자레이팅 GRN
※ 서버가 자동으로 설정
namestring
~ 128자레이팅 이름
레이팅 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring
~ 128자사용자ID
rateValuefloat1500.00 ~ 65535.0레이트 값
Glicko-2 알고리즘으로 계산된 플레이어의 현재 레이팅 점수입니다.
RatingModel에서 정의된 초기값(일반적으로 1500.0)이 기본값입니다.
대전 결과와 상대의 상대적인 실력에 따라 값이 증감합니다.
createdAtlong
현재 시각생성일시
UNIX 시간·밀리초
※ 서버가 자동으로 설정
updatedAtlong
현재 시각최종 갱신일시
UNIX 시간·밀리초
※ 서버가 자동으로 설정

EzJoinedSeasonGathering

참가 중인 시즌 게더링

특정 시즌과 티어에서 플레이어가 어느 시즌 게더링에 참가하고 있는지를 추적하는 레코드입니다.
플레이어가 시즌 게더링에 참가할 때 자동으로 생성되며, 플레이어의 현재 게더링을 빠르게 조회하기 위한 인덱스 역할을 합니다.
각 플레이어는 시즌과 티어의 조합마다 최대 1개의 시즌 게더링에 소속될 수 있습니다.

타입활성화 조건필수기본값값 제한설명
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonlong
0 ~ 9223372036854775805시즌
tierlong
0 ~ 9223372036854775805티어
비슷한 랭크의 플레이어를 그룹화하기 위한 티어 레벨입니다.
SeasonModel에서 지정된 GS2-Experience 모델에서의 플레이어 랭크에 따라 결정됩니다.
플레이어는 동일한 티어의 플레이어와만 매칭되어 공평한 대전이 보장됩니다.
seasonGatheringNamestring
~ 128자시즌 게더링명
이 플레이어가 참가하고 있는 시즌 게더링의 이름입니다.
동일 시즌·티어 내의 특정 시즌 게더링 엔티티를 참조하기 위해 사용됩니다.

EzSeasonGathering

시즌 게더링

시즌 기간 동안 플레이어를 모으는 영속적인 게더링입니다.
매치메이킹 완료 후 해산하는 일반 게더링과 달리, 시즌 게더링은 시즌 동안 계속 존속하며 참가자를 축적합니다.
플레이어는 티어(GS2-Experience의 랭크에 기반)와 시즌 번호로 그룹화되며, 각 시즌 게더링에는 SeasonModel에서 정의된 최대 참가 인원 제한이 있습니다.

타입활성화 조건필수기본값값 제한설명
seasonGatheringIdstring
~ 1024자시즌 개더링 GRN
※ 서버가 자동으로 설정
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonlong
0 ~ 9223372036854775805시즌
tierlong
0 ~ 9223372036854775805티어
비슷한 랭크의 플레이어를 그룹화하기 위한 티어 레벨입니다.
SeasonModel에서 지정된 GS2-Experience 모델에서의 플레이어 랭크에 따라 결정됩니다.
플레이어는 동일한 티어의 플레이어와만 매칭되어 공평한 대전이 보장됩니다.
namestring
UUID~ 128자시즌 게더링명
시즌 게더링 고유의 이름입니다. 영숫자 및 -(하이픈), _(언더스코어), .(마침표)로 지정합니다.
participantsList<string>[]0 ~ 1000 items참가자 사용자 ID 목록
이 시즌 게더링에 참가한 플레이어의 사용자 ID 목록입니다.
플레이어가 참가하면 이 목록에 추가되며, 최대 참가 인원에 도달할 때까지 시즌 동안 계속 증가합니다.

EzBallot

투표용지

레이팅이 적용된 매치메이킹 게임 종료 후, 각 플레이어가 대전 결과를 보고하기 위해 발급되는 투표용지입니다.
레이팅 모델 이름, 개더링 이름, 참가 인원수 등 대전의 컨텍스트 정보를 포함합니다.
각 플레이어는 서버에서 서명된 투표용지를 받아 게임 결과를 기입하여 Vote API에 제출합니다.
투표 시스템은 레이팅 계산을 확정하기 위해 제출된 투표용지의 50%를 초과하는 합의를 필요로 합니다.

타입활성화 조건필수기본값값 제한설명
userIdstring
~ 128자사용자ID
ratingNamestring
~ 128자레이팅 이름
이 대전 후의 레이팅 계산에 사용할 RatingModel의 이름입니다.
이 대전의 결과 처리에 적용되는 레이팅 시스템의 파라미터(초기값, 변동성)를 지정합니다.
gatheringNamestring
~ 128자개더링 이름
대전 결과 보고 대상이 되는 개더링의 이름입니다.
특정 매치메이킹 세션을 식별하고, 동일한 대전의 모든 참가자로부터의 투표를 연결하기 위해 사용됩니다.
numberOfPlayerint
2 ~ 10참가 인원수
이 대전에 참가한 플레이어의 총 인원수입니다.
예상되는 투표 수 결정 및 합의 검증(플레이어의 50%를 초과하는 인원이 일치하는 결과를 제출해야 함)에 사용됩니다.
2에서 10 사이의 범위로 지정합니다.

EzRatingModel

레이팅 모델

GS2에서는 레이팅 알고리즘으로 Glicko-2를 채택하고 있습니다.
Glicko-2에는 여러 파라미터가 있지만, GS2-Matchmaking에서는 이를 종합적으로 나타내는 변동성이라는 하나의 파라미터로 통합하고 있습니다.
변동성은 변화의 크기를 나타내는 파라미터로, 값이 클수록 레이팅 값의 변동 폭이 커집니다.

타입활성화 조건필수기본값값 제한설명
namestring
~ 128자레이팅 모델 이름
레이팅 모델 고유의 이름. 영숫자 및 -(하이픈), _(밑줄), .(마침표)로 지정합니다.
metadatastring~ 128자메타데이터
메타데이터에는 임의의 값을 설정할 수 있습니다.
이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다.
volatilityint1001 ~ 20000레이팅의 변동성
각 대전 후 레이트 값이 얼마나 변동하는지를 제어하는 Glicko-2의 파라미터입니다.
값이 클수록 레이팅의 변동 폭이 커져 더 빠르게 레이팅이 조정됩니다.
값이 작을수록 레이팅이 안정되어 완만하게 변화합니다. 기본값은 100입니다.

EzSeasonModel

시즌 모델

시즌 매치메이킹에서, 일정 기간 동안 유효한 영속 개더링의 기간·최대 참가 인원수·티어 연동 설정을 정의하는 마스터 데이터입니다.
GS2-Schedule을 통해 기간을 관리하며, 필요에 따라 GS2-Experience와 연동하여 동일한 티어 내에서 영속 개더링을 형성합니다.

타입활성화 조건필수기본값값 제한설명
namestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
metadatastring~ 128자메타데이터
메타데이터에는 임의의 값을 설정할 수 있습니다.
이 값들은 GS2의 동작에는 영향을 주지 않으므로, 게임 내에서 사용하는 정보를 저장하는 용도로 사용할 수 있습니다.
maximumParticipantsint
2 ~ 1000최대 참가 인원수
하나의 시즌 개더링에 참가할 수 있는 플레이어의 최대 인원수입니다.
이 상한에 도달하면 시즌 개더링은 만원 상태가 되어 더 이상 플레이어가 참가할 수 없게 됩니다.
2에서 1000 사이의 범위로 지정합니다.
experienceModelIdstring~ 1024자티어 관리용 경험치 모델 GRN
플레이어의 티어를 결정하기 위해 사용하는 GS2-Experience 경험치 모델의 GRN입니다.
이 경험치 모델에서의 플레이어 랭크가 매치메이킹의 티어로 사용되어, 비슷한 레벨의 플레이어끼리 그룹화됩니다.
지정하지 않으면 티어에 의한 그룹화가 비활성화되어, 레벨에 관계없이 모든 플레이어가 매칭됩니다.
challengePeriodEventIdstring
~ 1024자챌린지 기간 이벤트 GRN
이 시즌의 유효 기간을 정의하는 GS2-Schedule 이벤트의 GRN입니다.
이 이벤트가 활성화되어 있는 동안에만 시즌 개더링의 생성·참가가 가능합니다.
이벤트 기간이 종료되면 시즌이 종료되어 새로운 매치메이킹이 불가능해집니다.

EzPlayer

참가자 플레이어 정보

매치메이킹에 참가하는 플레이어를 나타내며, ID, 속성, 역할, 거부 목록을 포함합니다.
게더링에 참가할 때, 플레이어의 속성값, 희망하는 역할, 함께 플레이하고 싶지 않은 사용자 목록을 가진 Player 오브젝트가 생성됩니다.
플레이어의 속성은 게더링의 속성 범위 조건과 대조되며, 거부 목록은 원치 않는 페어링을 방지하기 위해 크로스체크됩니다.

타입활성화 조건필수기본값값 제한설명
userIdstring
~ 128자사용자ID
attributesList<EzAttribute>[]0 ~ 5 items속성값 목록
매치메이킹 조건 평가에 사용되는 플레이어의 이름이 지정된 수치 속성입니다.
각 속성은 게더링의 AttributeRange 조건과 대조되어 참가 자격이 판정됩니다.
게더링 생성 시 범위 조건을 설정하는 경우, 플레이어 자신의 속성값도 그 범위 내에 있어야 합니다. 최대 5건.
roleNamestring“default”~ 128자역할명
이 플레이어가 게더링에서 채우고자 하는 역할입니다.
역할 구분이 없는 일반적인 매치메이킹의 경우 기본값 “default"를 사용합니다.
역할 기반 매치메이킹의 경우, 플레이어의 구체적인 역할(예: “팔라딘”, “나이트”)을 지정하며, 게더링의 정원 정의에 있는 역할명 및 별칭과 매칭됩니다.
denyUserIdsList<string>[]0 ~ 100 items매칭 거부 사용자 ID 목록
이 플레이어가 매칭을 거부하는 사용자 ID의 블랙리스트입니다.
매치메이킹 시, 게더링에 이미 참가한 플레이어가 이 목록에 포함되어 있으면 해당 게더링에 참가할 수 없습니다.
반대로, 기존 참가자의 거부 목록에 이 플레이어가 포함되어 있는 경우에도 참가가 차단됩니다. 최대 100건.

EzAttributeRange

모집 조건

게더링에 참가하기 위한 속성의 허용 범위를 정의하는 조건입니다.
플레이어가 참가를 시도할 때, 대응하는 이름의 속성값이 지정된 최소값·최대값 범위 내에 있어야 합니다.
스킬 기반 또는 레벨 기반의 매치메이킹 필터를 작성하는 데 사용됩니다.

타입활성화 조건필수기본값값 제한설명
namestring
~ 128자속성명
이 범위 조건을 적용할 속성의 이름입니다.
조건이 평가되려면 플레이어의 속성 목록에 있는 속성명과 일치해야 합니다.
minint00 ~ 2147483646속성값의 최소값
게더링에 참가하기 위해 필요한 속성값의 하한(해당 값 포함)입니다.
속성값이 이 임계값보다 낮은 플레이어는 참가할 수 없습니다.
maxint00 ~ 2147483646속성값의 최대값
게더링에 참가 가능한 속성값의 상한(해당 값 포함)입니다.
속성값이 이 임계값을 초과하는 플레이어는 참가할 수 없습니다.

EzCapacityOfRole

모집 슬롯

개더링 내 특정 역할에 대한 모집 슬롯을 정의합니다.
각 역할은 이름, 선택적 별칭, 최대 정원, 현재 참가 중인 플레이어 목록을 가집니다.
역할 별칭을 사용하면 유연한 매칭이 가능합니다. 예를 들어 “탱크” 역할에 “팔라딘"과 “나이트"라는 별칭을 설정하면, 둘 중 어느 하위 역할을 지정한 플레이어도 탱크 슬롯을 채울 수 있습니다.
모든 역할의 참가자가 정원에 도달하면, 개더링의 매치메이킹이 완료됩니다.

타입활성화 조건필수기본값값 제한설명
roleNamestring“default”~ 128자역할 이름
이 모집 슬롯의 역할 이름.
역할 구분이 없는 일반적인 매치메이킹의 경우, 기본값 “default"를 사용합니다.
역할 기반 매치메이킹(예: “탱크”, “힐러”, “어태커”)의 경우, 여기에 역할 카테고리 이름을 지정합니다.
roleAliasesList<string>[]0 ~ 9 items역할 이름 별칭 목록
이 모집 슬롯에서 허용되는 대체 역할 이름.
이러한 별칭 중 하나를 역할 이름으로 지정한 플레이어는 이 슬롯에 매칭됩니다.
하위 역할 매칭을 가능하게 합니다. 예: “탱크” 역할에 대한 “팔라딘"과 “나이트” 별칭. 최대 9건.
capacityint
1 ~ 256모집 인원수
이 역할 슬롯을 채울 수 있는 플레이어의 최대 수.
참가자 수가 이 정원에 도달하면, 역할은 가득 차게 되어 더 이상 이 역할의 플레이어는 참가할 수 없습니다.
1에서 256 범위로 지정합니다.
participantsList<EzPlayer>[]0 ~ 1000 items참가자 플레이어 정보 목록
현재 이 역할 슬롯을 차지하고 있는 플레이어의 목록.
플레이어는 개더링에 참가하면 추가되고, 이탈하면 삭제됩니다.
각 플레이어 항목에는 사용자 ID, 속성, 역할 이름, 거부 목록이 포함됩니다. 사용자 ID를 기준으로 고유성이 보장됩니다.

EzAttribute

속성값

매치메이킹을 위해 플레이어에게 연결된 이름이 지정된 수치 속성입니다.
어떤 플레이어가 참가할 수 있는지 필터링하기 위해 개더링의 AttributeRange 조건과 함께 사용됩니다.
예를 들어 값이 50인 “레벨” 속성을 가진 플레이어는 레벨 40~60을 요구하는 개더링에 매칭됩니다.
각 플레이어는 최대 5개의 속성을 가질 수 있습니다.

타입활성화 조건필수기본값값 제한설명
namestring
~ 128자속성 이름
속성 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
valueint00 ~ 2147483646속성값
이 플레이어의 속성 수치입니다.
매치메이킹 시 개더링의 AttributeRange 조건에서 지정된 최소값·최대값 범위와 대조됩니다.

EzGameResult

대전 결과

Vote 시스템을 통한 레이팅 계산에 사용되는, 대전에서 한 플레이어의 결과를 나타냅니다.
각 GameResult 항목은 사용자 ID와 해당 대전에서의 순위(최종 순위)를 짝지어 나타냅니다.
순위 값이 작을수록 높은 성적을 나타냅니다(1위 = rank 1). 순위가 같은 플레이어는 무승부로 처리됩니다.

타입활성화 조건필수기본값값 제한설명
rankint
0 ~ 2147483646순위
대전에서 플레이어의 최종 순위입니다. 1이 최상위(승자)입니다.
Glicko-2 알고리즘에 의한 레이팅 변동 계산에 사용됩니다. 상위 플레이어는 레이팅이 상승하고, 하위 플레이어는 레이팅이 하락합니다.
순위가 같은 플레이어는 무승부로 처리됩니다.
userIdstring
~ 128자사용자ID

EzSignedBallot

서명된 투표용지

진위를 검증하기 위한 디지털 서명이 부여된 투표용지입니다.
매치메이킹 완료 후 서버가 플레이어에게 서명된 투표용지를 발급하여, 정당한 참가자만이 대전 결과를 제출할 수 있도록 보장합니다.
투표용지가 Vote API에 제출될 때 서명이 검증되어, 대전 컨텍스트(레이팅 이름, 개더링 이름, 참가 인원수)의 변조를 방지합니다.

타입활성화 조건필수기본값값 제한설명
bodystring
~ 1024자투표용지 본문
디지털 서명의 대상이 되는 직렬화된 투표용지 데이터입니다.
서명과 대조하여 검증 가능한 형식으로, 투표 컨텍스트(사용자 ID, 레이팅 이름, 개더링 이름, 참가 인원수)를 포함합니다.
signaturestring
~ 256자서명
투표용지 본문의 진위성과 무결성을 검증하기 위한 디지털 서명입니다.
GS2-Key의 암호화 키를 사용하여 서버에서 생성되며, 투표용지 제출 시 위조나 변조를 방지하기 위해 검증됩니다.

EzTimeSpan

시간 간격(기간)

일·시간·분으로 구성된 시간의 길이를 나타냅니다.
현재 시각으로부터의 게더링 유효 기간 등, 상대적인 시간 오프셋을 지정하는 데 사용됩니다.
전체 기간은 세 구성 요소를 합산하여 계산됩니다.

타입활성화 조건필수기본값값 제한설명
daysint00 ~ 365일수
기간에서의 일수입니다. 최대 365일. 기본값은 0입니다.
hoursint00 ~ 24시간
기간에서의 시간 수입니다. 최대 24시간. 기본값은 0입니다.
minutesint00 ~ 60
기간에서의 분 수입니다. 최대 60분. 기본값은 0입니다.

메서드

cancelMatchmaking

매치메이킹을 취소하고 기어링에서 이탈합니다

플레이어를 현재 참가 중인 기어링에서 이탈시키고 매치메이킹을 중단합니다.
매치메이킹 대기 화면에서 “취소” 버튼을 탭했을 때 사용합니다.

주의: 취소하려는 순간 매치메이킹이 완료된 경우, 기어링이 더 이상 존재하지 않기 때문에 NotFoundException(404 오류)이 반환됩니다.
게임 측에서는 이 경우를 처리해야 합니다. 매치가 성립되었다는 의미이므로 플레이어를 그대로 게임에 진행시키면 됩니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
gameSessionGameSession
GameSession

Result

타입설명
itemEzGathering취소한 개더링

구현 예제

    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();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).gathering(
        "gathering-0001"
    )

var async_result = await domain.cancel_matchmaking(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

createGathering

매치메이킹용 방(개더링) 신규 생성

매치메이킹용 방을 생성하고 다른 플레이어의 참가를 기다립니다.
개더링 생성 시 모집 조건을 설정합니다. 예를 들어 “어태커 1명과 힐러 1명 모집, 플레이어 레벨은 10~20"과 같은 조건을 지정할 수 있습니다.

주요 설정 항목:

  • capacityOfRoles: 역할별 모집 인원을 정의합니다(예: DPS 2명 + 탱커 1명 + 힐러 1명).
  • attributeRanges: 레벨이나 랭크 등 플레이어 속성에 기반한 참가 조건을 설정합니다.
  • allowUserIds: 특정 플레이어만 참가할 수 있도록 제한합니다(친구 전용 또는 초대제 매치메이킹에 유용합니다).
  • expiresAt: 개더링의 유효 기간을 설정합니다. 설정을 권장합니다. 유효 기간이 없으면 플레이어가 게임에서 이탈한 후에도 오래된 개더링이 계속 남아 있게 됩니다. 유효 기간을 사용하는 경우, 기간이 만료되면 플레이어에게 개더링을 다시 생성하도록 안내하는 구조로 만들어 주세요.

Player 파라미터에서 자기 자신의 사용자 ID는 생략할 수 있습니다.

개더링 생성 후, 다른 플레이어는 DoMatchmaking을 호출하여 이 개더링을 찾아 참가할 수 있습니다.
모든 역할 슬롯이 채워지면 매치메이킹이 완료되고 모든 참가자에게 알림이 전송됩니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession
playerEzPlayer
자신의 플레이어 정보
attributeRangesList<EzAttributeRange>[]0 ~ 5 items모집 조건
이 개더링에 참가하기 위해 플레이어가 충족해야 하는 속성 범위 조건의 목록입니다.
각 항목은 속성 이름과 허용되는 최소값·최대값 범위를 지정합니다.
플레이어 자신의 속성값이 이 범위 내에 있지 않으면 참가할 수 없습니다. 최대 5건.
capacityOfRolesList<EzCapacityOfRole>[]1 ~ 5 items모집 슬롯 목록
이 개더링의 모집 슬롯을 정의합니다.
각 항목은 역할 이름, 그 별칭, 그리고 해당 역할에 참가 가능한 최대 인원수를 지정합니다.
모든 역할 슬롯이 정원에 도달하면 매치메이킹이 완료됩니다. 최소 1건, 최대 5건.
allowUserIdsList<string>[]0 ~ 100 items참가 허용 사용자 ID 목록
이 게더링에 참가하는 것이 허용된 사용자 ID의 화이트리스트입니다.
지정한 경우, 목록에 포함된 사용자만 이 게더링의 매치메이킹에 참가할 수 있습니다.
친구 전용 매치메이킹이나 초대제 매치메이킹 시나리오에 유용합니다. 최대 100건.
expiresAtlong게더링 유효 기간
이 게더링이 자동으로 만료되어 삭제되는 시각입니다.
이 시각까지 매치메이킹이 완료되지 않으면 게더링은 정리됩니다.
지정하지 않은 경우, 매치메이킹이 완료되거나 수동으로 삭제될 때까지 게더링이 유지됩니다.
expiresAtTimeSpanEzTimeSpan유효기간까지 남은 시간

Result

타입설명
itemEzGathering작성한 개더링

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session)

var async_result = await domain.create_gathering(
    (Gs2MatchmakingPlayer.new()
        .with_attributes([
            (Gs2MatchmakingEzAttribute.new()
                .with_name("stage")
                .with_value(1)),
            (Gs2MatchmakingEzAttribute.new()
                .with_name("level")
                .with_value(10)),
        ])), # player
    [
        (Gs2MatchmakingEzAttributeRange.new()
            .with_name("stage")
            .with_min(1)
            .with_max(1)),
        (Gs2MatchmakingEzAttributeRange.new()
            .with_name("level")
            .with_min(0)
            .with_max(10)),
    ], # attribute_ranges
    [
        (Gs2MatchmakingEzCapacityOfRole.new()
            .with_role_name("default")
            .with_capacity(4)),
    ], # capacity_of_roles
    null, # allow_user_ids
    null, # expires_at
    null # expires_at_time_span
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

doMatchmaking

참가 가능한 개더링을 검색하여 참가

기존 개더링 중에서 플레이어의 속성에 맞고 빈 자리가 있는 것을 검색하여 자동으로 참가합니다.
직접 매치를 만들기보다 기존 매치에 참가하고 싶은 플레이어가 사용하는 메인 API입니다.

한 번의 호출에서는 일정 시간 동안만 검색을 수행합니다. 아직 적절한 개더링을 찾지 못한 경우 matchmakingContextToken이 반환됩니다.
다음 호출에서 이 토큰을 전달하면 이전 검색의 이어서부터 검색을 재개할 수 있습니다. 매치가 발견될 때까지 반복해서 호출해 주세요.

모든 개더링을 검색했지만 참가 가능한 것이 없었던 경우, 개더링과 토큰 모두 null이 됩니다.
이 경우에는 CreateGathering으로 새로운 개더링을 생성해 주세요.

일반적인 매치메이킹 흐름:

  1. DoMatchmaking을 반복 호출하며 매번 토큰을 전달
  2. 개더링이 반환됨 → 매치메이킹 성공, 게임으로 진행
  3. 개더링과 토큰 모두 null → 매치를 찾지 못했으므로 새로운 개더링을 생성

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession
playerEzPlayer
자신의 플레이어 정보
matchmakingContextTokenstring~ 5120자검색 재개에 사용하는 매치메이킹 상태를 보유하는 토큰

Result

타입설명
itemEzGathering참가한 개더링
matchmakingContextTokenstring매치메이킹 상태를 보유하는 토큰

구현 예제

    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

정원이 채워지지 않은 상태에서 매치메이킹을 조기 종료합니다

모든 역할 슬롯이 채워지기 전에 매치메이킹을 종료합니다.
원래 모집 인원보다 적은 인원으로 게임을 시작하고 싶을 때 사용합니다. 예를 들어 4인용 협력 던전을 3명으로 시작하는 경우입니다.

이 API를 호출할 수 있는 것은 기어링을 생성한 플레이어뿐입니다.
호출 후 매치메이킹은 완료된 것으로 처리되며, 모든 참가자에게 매치 완료 알림이 전송됩니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
gameSessionGameSession
GameSession

Result

타입설명
itemEzGathering취소한 개더링

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).gathering(
        "gathering-0001"
    )

var async_result = await domain.early_complete_matchmaking(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

getGathering

기어링의 현재 상태를 취득합니다

특정 기어링의 최신 정보를 취득합니다. 참가자, 모집 조건, 역할별 정원이 포함됩니다.
대기 화면을 표시할 때 사용합니다. 예를 들어 “2/4명 참가 완료, 모집 중: 탱커 1명, 힐러 1명"과 같은 화면을 표시할 수 있습니다.

모든 역할 슬롯이 채워졌는지 확인함으로써 매치메이킹이 완료되었는지 확인하는 용도로도 사용할 수 있습니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.

Result

타입설명
itemEzGathering개더링

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).user(
        "user-0001"
    ).gathering(
        "gathering-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).User(
        userId: "user-0001"
    ).Gathering(
        gatheringName: "gathering-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->User(
        "user-0001" // userId
    )->Gathering(
        "gathering-0001" // gatheringName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FGathering> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).user(
        "user-0001"
    ).gathering(
        "gathering-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

ping

매치메이킹 대기 중 킵얼라이브를 전송합니다

플레이어가 아직 매치메이킹을 대기 중임을 서버에 알립니다.
플레이어가 매치메이킹 대기 화면에 있는 동안 주기적으로 호출하세요.

이를 통해 어떤 플레이어가 아직 온라인 상태로 대기 중인지 시스템이 파악할 수 있습니다.
네임스페이스에 타임아웃이 설정되어 있는 경우, 타임아웃 시간 내에 ping을 보내지 않은 플레이어는 기어링에서 자동으로 제외될 수 있습니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.

Result

타입설명
itemEzGathering갱신한 개더링

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).gathering(
        "gathering-0001"
    )

var async_result = await domain.ping(
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

updateGathering

개더링의 모집 조건 변경

아직 플레이어를 기다리고 있는 기존 개더링의 속성 범위 조건을 변경합니다.
예를 들어 “레벨 1520” 조건으로 플레이어가 모이지 않는 경우, “레벨 1025"로 범위를 넓혀 참가 가능한 플레이어 모수를 늘릴 수 있습니다.

변경할 수 있는 것은 속성 범위뿐입니다. 역할 정원이나 참가 허용 사용자 ID는 생성 후에는 변경할 수 없습니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
gameSessionGameSession
GameSession
attributeRangesList<EzAttributeRange>[]0 ~ 5 items모집 조건
이 개더링에 참가하기 위해 플레이어가 충족해야 하는 속성 범위 조건의 목록입니다.
각 항목은 속성 이름과 허용되는 최소값·최대값 범위를 지정합니다.
플레이어 자신의 속성값이 이 범위 내에 있지 않으면 참가할 수 없습니다. 최대 5건.

Result

타입설명
itemEzGathering갱신한 개더링

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).gathering(
        "gathering-0001"
    )

var async_result = await domain.update_gathering(
    [
        (Gs2MatchmakingEzAttributeRange.new()
            .with_name("stage")
            .with_min(1)
            .with_max(1)),
        (Gs2MatchmakingEzAttributeRange.new()
            .with_name("level")
            .with_min(0)
            .with_max(50)),
    ] # attribute_ranges
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

getRatingModel

특정 레이팅 설정의 상세 정보를 취득합니다

이름을 지정하여 하나의 레이팅 모델의 상세 정보를 취득합니다.
레이팅 시스템의 설정(초기 레이팅 값 및 변동성 파라미터)을 표시할 때 사용합니다.

변동성이 높을수록 대전마다 레이팅 변동 폭이 커지며(신규 플레이어의 실력을 빠르게 반영하는 데 적합), 변동성이 낮을수록 더 안정적이고 완만한 변화가 나타납니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
ratingNamestring
~ 128자레이팅 모델 이름
레이팅 모델 고유의 이름. 영숫자 및 -(하이픈), _(밑줄), .(마침표)로 지정합니다.

Result

타입설명
itemEzRatingModel레이팅 모델

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).rating_model(
        "mode1"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).RatingModel(
        ratingName: "mode1"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->RatingModel(
        "mode1" // ratingName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FRatingModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).rating_model(
        "mode1"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

listRatingModels

레이팅 설정 목록을 취득합니다

네임스페이스에 설정되어 있는 모든 레이팅 모델을 취득합니다.
각 레이팅 모델은 플레이어의 실력 평가 시스템에 대한 파라미터를 정의합니다. 예를 들어 “랭크 배틀”, “아레나”, “토너먼트"별로 각각 다른 레이팅을 가질 수 있습니다.

GS2에서는 레이팅 계산에 Glicko-2 알고리즘을 사용합니다. 각 모델은 초기 레이팅 값(기본값: 1500)과 변동성(대전마다 레이팅이 얼마나 크게 변하는지)을 지정합니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.

Result

타입설명
itemsList<EzRatingModel>레이팅 모델 리스트

구현 예제

    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());
    }
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRatingModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRatingModels(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRatingModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRatingModels(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeRatingModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeRatingModels(CallbackId);

getRating

특정 카테고리의 플레이어 레이팅 점수를 취득합니다

지정된 레이팅 이름에 대한 플레이어의 현재 레이팅 값을 취득합니다.
하나의 레이팅을 표시할 때 사용합니다. 예를 들어 대전 결과 화면이나 로비에서 “당신의 랭크 배틀 레이팅: 1823"과 같이 표시할 수 있습니다.

레이팅 값은 플레이어가 이기면 오르고 지면 내려갑니다. 변동 폭은 상대방의 레이팅과 변동성 설정에 따라 결정됩니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession
ratingNamestring
~ 128자레이팅 이름
레이팅 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.

Result

타입설명
itemEzRating레이팅

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).rating(
        "rating-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Rating(
        ratingName: "rating-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Rating(
        "rating-0001" // ratingName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FRating> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).rating(
        "rating-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

listRatings

모든 레이팅 카테고리에 대한 플레이어의 레이팅 점수를 취득합니다

플레이어의 현재 레이팅 값을 모두 취득합니다.
게임에 여러 레이팅 카테고리(예: “랭크 배틀"과 “아레나”)가 있는 경우, 각각의 점수가 반환됩니다.

프로필 화면이나 전적 화면을 만들 때 사용합니다. 예를 들어 “랭크 배틀: 1823, 아레나: 1547"과 같이 표시할 수 있습니다.
플레이어의 레이팅은 레이팅이 적용되는 매치에 처음 참가했을 때 자동으로 생성되며, 초기값(일반적으로 1500)부터 시작합니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession
pageTokenstring~ 1024자데이터 취득을 시작할 위치를 지정하는 토큰
limitint301 ~ 1000조회한 데이터 건수

Result

타입설명
itemsList<EzRating>레이팅 리스트
nextPageTokenstring목록의 나머지를 취득하기 위한 페이지 토큰

구현 예제

    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());
    }
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRatings(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRatings(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeRatings(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeRatings(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeRatings(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeRatings(CallbackId);

createVote

대전 결과 보고용 서명된 투표용지를 생성합니다

대전 결과를 보고할 때 사용하는 투표용지(밸럿)를 생성합니다.
레이팅이 적용되는 대전이 끝난 후, 각 플레이어는 누가 이기고 누가 졌는지 보고해야 합니다. 이 API는 플레이어의 신원 정보와 암호 서명이 포함된 위변조 방지 투표용지를 생성합니다.

대전 결과 보고 흐름:

  1. 대전이 종료되고, 각 플레이어의 게임 클라이언트가 CreateVote를 호출하여 서명된 투표용지를 취득한다
  2. 각 플레이어가 투표용지와 대전 결과를 Vote API로 전송한다
  3. 서버가 모든 투표를 집계하여 다수결로 최종 결과를 결정한다
  4. 확정된 결과에 따라 플레이어의 레이팅이 업데이트된다

파라미터:

  • ratingName: 이 대전이 속한 레이팅 카테고리의 이름(예: “ranked_battle”)
  • gatheringName: 이 대전이 진행된 기어링(매치메이킹 룸)의 이름
  • numberOfPlayer: 대전 참가 인원 수(2~10명)
  • keyId: 투표용지 서명에 사용할 암호화 키(커스텀 키를 설정하지 않은 경우 기본 키를 사용)

반환된 투표용지 본문과 서명은 Vote 또는 VoteMultiple API 호출에 필요합니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
ratingNamestring
~ 128자레이팅 모델 이름
레이팅 모델 고유의 이름. 영숫자 및 -(하이픈), _(밑줄), .(마침표)로 지정합니다.
gatheringNamestring
UUID~ 128자개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
gameSessionGameSession
GameSession
numberOfPlayerint
2 ~ 10참가 인원
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024자암호화 키 GRN

Result

타입설명
itemEzBallot투표용지
bodystring서명 대상 데이터
signaturestring서명 데이터

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).ballot(
        "rating-0001",
        "gathering-0001",
        4,
        "key-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Ballot(
        ratingName: "rating-0001",
        gatheringName: "gathering-0001",
        numberOfPlayer: 4,
        keyId: "key-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    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"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    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
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FBallot> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).ballot(
        "rating-0001",
        "gathering-0001",
        4,
        "key-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

vote

대전 결과 투표를 제출합니다

대전 후, 각 플레이어가 이 API를 개별적으로 호출하여 누가 이기고 누가 졌는지 보고합니다.
CreateVote로 취득한 투표용지 본문과 서명, 그리고 대전 결과(각 플레이어의 순위나 승패 목록)를 전달합니다.

투표 방식:

  • 첫 번째 플레이어가 투표한 후, 다른 플레이어들이 투표할 수 있는 유예 시간은 5분입니다
  • 5분 이내에 모든 플레이어가 투표하면 결과가 즉시 확정됩니다
  • 5분 이내에 일부 플레이어가 투표하지 않으면, 그때까지 접수된 투표 내용으로 다수결에 따라 결과가 결정됩니다
  • 표가 동수인 경우(예: 2명이 “플레이어 A 승리”, 2명이 “플레이어 B 승리”), 결과는 폐기되고 레이팅은 업데이트되지 않습니다(이 동작은 스크립트로 커스터마이즈할 수 있습니다)

가장 단순한 방식으로, 각 플레이어가 독립적으로 투표합니다. 단점은 결과 반영에 최대 5분이 걸릴 수 있다는 점입니다.

즉시 결과를 반영하고 싶다면 VoteMultiple을 사용하세요. 승리한 플레이어가 전원의 투표용지를 모아서 함께 전송합니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
ballotBodystring
~ 1024자투표용지의 서명 대상 데이터
ballotSignaturestring
~ 256자투표용지의 서명
gameResultsList<EzGameResult>0 ~ 10 items투표 내용. 대전을 진행한 플레이어 그룹 1에 속한 사용자 ID 리스트
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024자암호화 키 GRN

Result

타입설명
itemEzBallot투표용지

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    )

var async_result = await domain.vote(
    "ballotBody...", # ballot_body
    "ballotSignature...", # ballot_signature
    [
        Gs2MatchmakingEzGameResult.new()
            .with_rank(1)
            .with_user_id("user-0001"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(2)
            .with_user_id("user-0002"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(2)
            .with_user_id("user-0003"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(3)
            .with_user_id("user-0004"),
    ], # game_results
    "key-0001" # key_id
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

voteMultiple

모든 투표용지를 모아 한 번에 제출하여 대전 결과를 즉시 확정합니다

각 플레이어가 개별적으로 투표하는 방식(최대 5분 소요) 대신, 승리한 플레이어가 전원의 서명된 투표용지를 모아 한 번에 제출합니다. 이를 통해 결과가 즉시 확정됩니다.

권장 흐름:

  1. 대전 종료 — 각 플레이어가 CreateVote를 호출하여 서명된 투표용지를 취득한다
  2. 각 플레이어가 게임의 통신 수단(게임 서버나 P2P 통신 등)을 이용해 자신의 투표용지(본문 + 서명)를 승리한 측의 플레이어에게 전달한다
  3. 승리한 측의 플레이어가 VoteMultiple을 호출하여 수집한 모든 투표용지와 대전 결과를 전송한다
  4. 결과가 즉시 확정되고 레이팅이 업데이트된다

왜 승리한 측이 투표용지를 모으는가:

  • 패배한 측은 이겼다고 거짓말할 이유가 없지만(얻을 것이 없으므로), 투표용지 제출을 거부할 수도 있습니다
  • 패배한 측이 협조하지 않더라도, 과반수의 투표용지(절반 초과)만 있으면 결과는 승인됩니다
  • 예를 들어 2대2 대전에서 승리한 2명이 투표용지를 제출하면 4명 중 2명분 — 과반수로 충분합니다

구현은 다소 복잡해지지만 결과가 즉시 반영되므로 플레이어 경험 측면에서는 더 나은 방식입니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
signedBallotsList<EzSignedBallot>0 ~ 10 items서명이 첨부된 투표용지 리스트
gameResultsList<EzGameResult>0 ~ 10 items투표 내용. 대전을 진행한 플레이어 그룹 1에 속한 사용자 ID 리스트
keyIdstring“grn:gs2:{region}:{ownerId}:key:default:key:default”~ 1024자암호화 키 GRN

Result

타입설명
itemEzBallot투표용지

구현 예제

    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;
    }

    // 변경된 값 / 결과 값을 취득
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    )

var async_result = await domain.vote_multiple(
    [
        Gs2MatchmakingEzSignedBallot.new()
            .with_body("aaa")
            .with_signature("bbb"),
        Gs2MatchmakingEzSignedBallot.new()
            .with_body("aaa")
            .with_signature("bbb"),
        Gs2MatchmakingEzSignedBallot.new()
            .with_body("aaa")
            .with_signature("bbb"),
        Gs2MatchmakingEzSignedBallot.new()
            .with_body("aaa")
            .with_signature("bbb"),
    ], # signed_ballots
    [
        Gs2MatchmakingEzGameResult.new()
            .with_rank(1)
            .with_user_id("user-0001"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(2)
            .with_user_id("user-0002"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(2)
            .with_user_id("user-0003"),
        Gs2MatchmakingEzGameResult.new()
            .with_rank(3)
            .with_user_id("user-0004"),
    ], # game_results
    "key-0001" # key_id
)
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result

getJoinedSeasonGathering

특정 시즌에서 플레이어가 참가한 시즌 개더링 조회

지정된 시즌 번호에서 플레이어가 속한 시즌 개더링을 조회합니다.
현재 시즌에서 플레이어가 어느 매치 그룹에 있는지 확인할 때 사용합니다. 예를 들어, 앱 재시작 후 매치 로비 화면을 복원하는 경우입니다.

지정된 시즌에서 플레이어가 시즌 개더링에 참가하지 않은 경우, 또는 개더링이 이미 존재하지 않는 경우 정보는 반환되지 않습니다.
이 경우에는 DoSeasonMatchmaking으로 새로운 매치메이킹 검색을 시작해 주세요.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonlong0 ~ 9223372036854775805시즌
gameSessionGameSession
GameSession

Result

타입설명
itemEzJoinedSeasonGathering시즌 개더링

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).season(
        "season-0001",
        0
    ).joined_season_gathering(
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    ).JoinedSeasonGathering(
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    )->JoinedSeasonGathering(
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FJoinedSeasonGathering> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).me(game_session).season(
        "season-0001",
        0
    ).joined_season_gathering(
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

listJoinedSeasonGatherings

플레이어가 참가한 시즌 개더링 목록 조회

플레이어가 현재 멤버로 속해 있는 모든 시즌 개더링을 조회합니다.
대전 이력이나 활성 대전 화면을 표시할 때 사용합니다. 예를 들어, 이번 시즌에 플레이어가 참가 중이거나 참가한 랭크전을 목록으로 표시할 수 있습니다.

시즌 이름으로 필터링하여 특정 랭크 모드(예: 「랭크 1v1」만)의 대전만 표시할 수도 있습니다.

주요 용도:

  • 게임 실행 시 플레이어의 현재 활성 대전을 표시
  • 대전 이력 화면을 구성
  • 새로운 매치메이킹 검색을 시작하기 전에 플레이어가 이미 대전 중인지 확인

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonNamestring~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession

Result

타입설명
itemsList<EzJoinedSeasonGathering>시즌 개더링 목록
nextPageTokenstring목록의 나머지를 취득하기 위한 페이지 토큰

구현 예제

    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());
    }
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeJoinedSeasonGatherings(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeJoinedSeasonGatherings(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Season(
        seasonName: "season-0001",
        season: 0
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeJoinedSeasonGatherings(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeJoinedSeasonGatherings(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Season(
        "season-0001", // seasonName
        0 // season
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeJoinedSeasonGatherings(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeJoinedSeasonGatherings(CallbackId);

doSeasonMatchmaking

참가 가능한 시즌 매치를 검색하여 참가합니다

플레이어의 티어 내에서 빈 자리가 있는 시즌 기어링(영속적인 매치메이킹 그룹)을 검색하여 자동으로 참가합니다.
플레이어의 티어는 연동된 GS2-Experience 모델의 경험치 레벨에 따라 결정되므로, 실력이 비슷한 플레이어끼리 매칭됩니다.

일반적인 DoMatchmaking과 비슷한 구조이지만, 티어에 따른 그룹 분류가 있습니다:

  • 한 번의 호출로는 일정 시간만 검색합니다. 아직 매치를 찾지 못한 경우 matchmakingContextToken이 반환됩니다.
  • 다음 호출 시 이 토큰을 전달하면 이전 검색을 이어서 재개할 수 있습니다.
  • 매치가 발견될 때까지 반복해서 호출하세요.

모든 시즌 기어링을 검색해도 빈 자리가 없는 경우, 시즌 기어링과 토큰 모두 null로 반환됩니다.
일반 매치메이킹에서는 직접 새로운 기어링을 생성하지만, 시즌 매치메이킹에서는 필요에 따라 시스템이 자동으로 새로운 시즌 기어링을 생성합니다.

일반적인 시즌 매치메이킹 흐름:

  1. DoSeasonMatchmaking을 루프로 호출하며 매번 토큰을 전달한다
  2. 시즌 기어링이 반환됨 → 매치 성립, 게임으로 진행
  3. 둘 다 null → 현재 이용 가능한 매치가 없음. “검색 중” 화면을 표시하고 잠시 대기 후 재시도

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gameSessionGameSession
GameSession
matchmakingContextTokenstring~ 5120자검색 재개에 사용하는 매치메이킹 상태를 보유하는 토큰

Result

타입설명
itemEzSeasonGathering참가한 시즌 개더링
matchmakingContextTokenstring매치메이킹 상태를 보유하는 토큰

구현 예제

    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

시즌 기어링의 현재 상태를 취득합니다

특정 시즌 기어링의 상세 정보를 취득합니다. 참가자 목록과 소속 티어 정보가 포함됩니다.
시즌 매치의 로비나 대기 화면을 표시할 때 사용합니다. 예를 들어 “골드 티어 매치 #42: 3/4명 참가 중"과 같은 화면을 표시할 수 있습니다.

정확한 시즌 기어링을 특정하려면 시즌 번호, 티어, 기어링 이름을 지정해야 합니다.
이 정보는 DoSeasonMatchmaking을 통해 시즌 기어링 참가에 성공했을 때 반환됩니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonlong0 ~ 9223372036854775805시즌
tierlong
0 ~ 9223372036854775805티어
비슷한 랭크의 플레이어를 그룹화하기 위한 티어 레벨입니다.
SeasonModel에서 지정된 GS2-Experience 모델에서의 플레이어 랭크에 따라 결정됩니다.
플레이어는 동일한 티어의 플레이어와만 매칭되어 공평한 대전이 보장됩니다.
seasonGatheringNamestring
UUID~ 128자시즌 게더링명
시즌 게더링 고유의 이름입니다. 영숫자 및 -(하이픈), _(언더스코어), .(마침표)로 지정합니다.

Result

타입설명
itemEzSeasonGathering시즌 개더링

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).user(
        "user-0001"
    ).season(
        "season-0001",
        0
    ).season_gathering(
        0,
        "gathering-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    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 callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    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"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    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
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FSeasonGathering> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).user(
        "user-0001"
    ).season(
        "season-0001",
        0
    ).season_gathering(
        0,
        "gathering-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

getSeasonModel

특정 시즌 매치메이킹 설정의 상세 정보를 취득합니다

이름을 지정하여 하나의 시즌 모델의 상세 정보를 취득합니다.
특정 랭크 모드의 규칙이나 설정을 표시할 때 사용합니다. 예를 들어 모드 선택 화면에서 “랭크 1대1: 최대 2명, 아레나 경험치로 티어 결정"과 같이 표시할 수 있습니다.

응답에는 다음이 포함됩니다:

  • maximumParticipants: 한 경기에 참가할 수 있는 인원 수
  • experienceModelId: 플레이어의 티어를 결정하는 데 사용되는 GS2-Experience 모델. 플레이어의 경험치 레벨이 티어에 매핑되며, 같은 티어 내의 플레이어끼리만 매칭됩니다.
  • challengePeriodEventId: 설정되어 있는 경우, 지정된 기간 동안만 랭크전에 참가할 수 있습니다(예: 주말만, 매일 19시~22시 등)

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
seasonNamestring
~ 128자시즌 모델 이름
시즌 모델 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.

Result

타입설명
itemEzSeasonModel시즌 모델

구현 예제

    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;
    }
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).season_model(
        "season-0001"
    )

var async_result = await domain.model()
if async_result.error != null:
    push_error(str(async_result.error))
    return

var result = async_result.result
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    ).SeasonModel(
        seasonName: "season-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.Subscribe(
        value => {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    )->SeasonModel(
        "season-0001" // seasonName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::Matchmaking::Model::FSeasonModel> value) {
            // 값이 변화했을 때 호출됨
            // value에는 변경 후의 값이 전달됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->Unsubscribe(CallbackId);
var domain = ez.matchmaking.namespace_(
        "namespace-0001"
    ).season_model(
        "season-0001"
    )

# 이벤트 핸들링 시작
var callback_id = domain.subscribe_model(func(value):
    # 값이 변화했을 때 호출됨
    # value에는 변경 후의 값이 전달됩니다
    pass
)

# 이벤트 핸들링 정지
domain.unsubscribe_model(callback_id)

listSeasonModels

시즌 매치메이킹 설정 목록을 취득합니다

네임스페이스에 정의되어 있는 모든 시즌 모델을 취득합니다.
시즌 매치메이킹은 랭크전이 있는 대전 게임을 위해 설계되었습니다. “시즌 1”, “시즌 2"와 같이 기간별로 구분하고, 플레이어를 실력에 따라 티어(등급)로 나누어 매칭합니다.

일반적인 기어링 기반 매치메이킹(임시 방을 생성하는 방식)과 달리, 시즌 매치메이킹에서는 시즌 동안 계속 유지되는 영속적인 그룹을 사용합니다.
같은 티어의 플레이어끼리 매칭되므로 공정한 대전이 가능합니다.

각 시즌 모델은 다음을 정의합니다:

  • 한 경기당 최대 참가 인원
  • 플레이어의 티어를 계산하는 데 사용되는 경험치 모델(GS2-Experience와 연동하여 브론즈, 실버, 골드 등의 실력대를 결정합니다)
  • 선택적인 챌린지 기간 이벤트(GS2-Schedule과 연동하여 대전 가능한 시간대를 제한할 수 있습니다)

이용 가능한 랭크 모드 목록을 표시할 때 사용합니다. 예를 들어 “랭크 1대1”, “랭크 3대3"과 같은 화면입니다.

Request

타입활성화 조건필수기본값값 제한설명
namespaceNamestring
~ 128자네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.

Result

타입설명
itemsList<EzSeasonModel>시즌 모델 목록

구현 예제

    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());
    }
값 변경 이벤트 핸들링
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeSeasonModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeSeasonModels(callbackId);
    var domain = gs2.Matchmaking.Namespace(
        namespaceName: "namespace-0001"
    );

    // 이벤트 핸들링 시작
    var callbackId = domain.SubscribeSeasonModels(
        () => {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    domain.UnsubscribeSeasonModels(callbackId);
    const auto Domain = Gs2->Matchmaking->Namespace(
        "namespace-0001" // namespaceName
    );

    // 이벤트 핸들링 시작
    const auto CallbackId = Domain->SubscribeSeasonModels(
        []() {
            // 리스트의 요소가 변화했을 때 호출됨
        }
    );

    // 이벤트 핸들링 정지
    Domain->UnsubscribeSeasonModels(CallbackId);

이벤트 핸들러

OnJoinNotification

개더링에 새로운 참가자가 참가했을 때 사용하는 푸시 알림

이름타입설명
namespaceNamestring네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
joinUserIdstring사용자ID

구현 예제

    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;
    });
    ez.matchmaking.join_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var gathering_name = notification.gathering_name
        var join_user_id = notification.join_user_id
    )

OnLeaveNotification

개더링에서 참가자가 이탈했을 때 사용하는 푸시 알림

이름타입설명
namespaceNamestring네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.
leaveUserIdstring사용자ID

구현 예제

    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;
    });
    ez.matchmaking.leave_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var gathering_name = notification.gathering_name
        var leave_user_id = notification.leave_user_id
    )

OnCompleteNotification

매치메이킹이 성립했을 때 사용하는 푸시 알림

이름타입설명
namespaceNamestring네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
gatheringNamestring개더링 이름
개더링의 고유한 이름을 보유합니다.
이름은 UUID(Universally Unique Identifier) 형식으로 자동 생성되며, 개더링을 식별하기 위해 사용됩니다.

구현 예제

    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;
    });
    ez.matchmaking.complete_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var gathering_name = notification.gathering_name
    )

OnChangeRatingNotification

레이팅 값이 변동했을 때 사용하는 푸시 알림

이름타입설명
namespaceNamestring네임스페이스 이름
네임스페이스 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
ratingNamestring레이팅 이름
레이팅 고유의 이름입니다. 영숫자 및 -(하이픈) _(언더스코어) .(마침표)로 지정합니다.
userIdstring사용자ID
rateValuefloat레이트 값
Glicko-2 알고리즘으로 계산된 플레이어의 현재 레이팅 점수입니다.
RatingModel에서 정의된 초기값(일반적으로 1500.0)이 기본값입니다.
대전 결과와 상대의 상대적인 실력에 따라 값이 증감합니다.

구현 예제

    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;
    });
    ez.matchmaking.change_rating_notification.connect(func(notification):
        var namespace_name = notification.namespace_name
        var rating_name = notification.rating_name
        var user_id = notification.user_id
        var rate_value = notification.rate_value
    )