매치메이킹 가이드

누군가와 같이 플레이(또는 상대하여)하기 위하여 룸에 입장하는 것은 Photon 에서 매우 쉽습니다. 기본적으로 3가지의 접근 방식이 있습니다: 서버에게 매칭되는 룸을 찾아 달라고 하는 것, 친구를 따라 룸에 입장하거나 룸의 목록을 얻어 사용자가 하나를 선택 하는 것 입니다.

저희는 서버측에서 매치메이킹을 하여 빠르고 어려움없이 사용하는 것이 현대의 게임에 가장 최적이라고 생각합니다. 따라서 룸 목록을 사용하는 것은 그리 권장하고 있지 않습니다. 아래에는 내가 직접 하려는 생각을 가지고 있다면 기억해야할 옵션들과 사항에 대해서 설명합니다.

크로스 플랫폼 매치메이킹 체크리스트

설계 사상에 의하여 Photon 클라우드에서는 다른 지역간 게임은 할 수 없습니다.

기기 또는 플랫폼에 관계 없이 동일한 지역에 접속한 플레이어간에만 플레이 할 수 있습니다.

플레이어 매칭에 문제가 발생하고 있다면 다음의 체크리스트로 검토 해보세요:

  • 모든 클라이언트들이 동일한 AppId, AppVersionRegion 을 이용하고 있는지 확인 합니다.
  • 이름으로 룸 참여를 시도하기 전에, 생성된 룸인지 아니면 JoinOrCreateRoom 메소드를 사용하였는지 확인 합니다.
  • 무작위 룸에 참여 하고 있다면 생성 할 때와 동일한 로비(이름과 타입)를 선택 했는지 확인 합니다.

무작위 매치메이킹

여기에서 설명되고 있는 작업흐름은 룸의 긴 목록에서 하나를 선택하라고(무작위로) 묻지 않고 룸에 플레이어들이 참가하는 방식입니다.

빠르게 룸에 플레이어를 입장시키기 원하면 다음을 따라 진행하세요:

  • "무작위로 참가" 시도를 합니다. 이 오퍼레이션의 이름은 API/플랫폼에 따라 다르며 OpJoinRandom 또는 JoinRandomRoom 입니다.
  • 최고의 경우는 이게 끝입니다. 클라이언트는 성공적으로 룸에 참가 할 것 입니다.
  • 최악의 경우는 룸이 존재 하지 않거나 룸에 참여할 수 있는 공간이 없는 경우 입니다.
  • 룸을 찾을 수 없다면 즉시 새로운 룸을 생성합니다!
  • 룸 이름이 보이지 않는다면 이름을 구성하지 마세요. 서버가 이 일을 하도록 두세요! OpCreateRoom 을 호출 할 때 "room name" 을 null 또는 "" 로 설정합니다. 룸의 이름은 유일한 GUID 가 됩니다.
  • "max players" 값을 적용 합니다. 이런 방식을 통해 서버는 계속 플레이어가 추가되는 것을 방지 합니다.
  • 클라이언트가 룸에 혼자 있을 때(players == 1): 기다리세요. 화면에 상대편을 기다리고 있다고 보여주세요.
  • 룸에 충분한 플레이어들이 모였을 때 게임을 "시작"할 수 있습니다. 더이상 새로운 플레이어를 입장시키지 않기 위해서 룸을 "close" 하세요. 서버는 룸이 다 차지 않았더라도 새로운 플레이어가 입장하는 것을 막을 것 입니다.
  • 노트: 룸을 닫았을 때 이미 들어 오려고 하는 플레이어들이 있는 매우 짧은 시간이 있을 수 있습니다. 룸을 닫아도 플레이어가 참여 하는 것에 놀라지는 마세요.

이 흐름을 사용하면 플레이어들의 게임 참가는 식은 죽 먹기 입니다.

이러한 방식을 사용할 때 클라이언트의 설정이 "Auto-Join Lobby" 으로 설정되어 있는지 체크 하세요.(파라미터 이름이 "autoJoinLobby" 또는 유사합니다) 클라이언트가 참여 흐름의 속도 증가를 위해 이 값이 false로 되어 있는지 확인 해 주세요.

무작위 매치메이킹이 아닙니다

항상 모든 플레이어들이 무작위 매치메이킹을 즐기지는 않습니다. 특정 맵 또는 모드(2대2 대결 등)에서 플레이를 하고 싶을 때도 있습니다. Photon Cloud 와 Loadbalancing 에서는 임의적인 "커스텀 룸 프로퍼티"를 설정할 수 있고 JoinRandom 에서 필터로 이용할 수 있습니다.

룸 프로퍼티와 로비

룸 프로퍼티들은 동일한 룸에 있는 모든 플레이들과 동기화되고 현재의 맵, 라운드, 시작시간등을 추적하는데 유용하게 사용 할 수 있습니다. 룸 프로퍼티는 문자열 키를 가진 해시테이블로 처리 됩니다. 예를 들어 "GameMode" 대신에 "gm" 처럼 사용하는 간단한 이름이 더 좋습니다. 기본적으로 프로퍼티들은 독립적으로 유지 하기 위해서 마스터 서버로 전송되지는 않습니다. "map" 과 "game mode"를 매치메이킹에 이용하려면 룸을 생성할 때 "로비에서 보여지는 룸 프로퍼티들"을 설정할 수 있습니다.

RoomOptions roomOptions = new RoomOptions();
roomOptions.CustomRoomPropertiesForLobby = { "map", "ai" };
roomOptions.CustomRoomProperties = new Hashtable() { { "map", 1 } };
roomOptions.MaxPlayers = expectedMaxPlayers;
lbClient.OpCreateRoom(roomName, roomOptions, typedLobby);

"ai"에는 아직 값이 없다는 것을 주목 하세요. Room.SetCustomProperties 를 통해서 게임내에서 설정되기 전까지는 로비에 나타나지 않을 것 입니다. "map" 또는 "ai"의 값을 변경할 때 약간의 지연과 함께 로비에서 값이 갱신 될 것 입니다. 이 리스트는 클라이언트가 리스트를 로드 할 때 부하가 걸리지 않도록 되도록 짧게 유지 하도록 하세요.

다시 한 번 말씀 드리지만 : roomPropsInLobby 를 이용하기 위해 로비에 참여 (긴 룸 목록의 취득)할 필요는 없습니다. 로비에서 무엇인가를 설정 해 놓았을 때 필터로써 사용할 수 있습니다.

무작위 참여시 룸 프로퍼티 필터링

OpJoinRandom에서 예측되는 룸 프로퍼티들과 최대 플레이어 숫자를 해시테이블로 전달 할 수 있습니다. 이러한 값들은 서버가 나에게 맞는 룸을 선택할 때 필터로 동작하게 됩니다.

Hashtable expectedCustomRoomProperties = new Hashtable() { { "map", 1 } };
lbClient.OpJoinRandomRoom(expectedCustomRoomProperties, expectedMaxPlayers);

더 많은 필터 프로퍼티들을 전달하게 되면 필터에 맞는 룸이 적어지게 됩니다. 제한을 위해서 좋은 옵션입니다. 로비가 모르는 프로퍼티를 필터로 사용 하지는 마세요( 상단참조)

친구와 플레이

만약 친구들과 소통하는 유저들이면(예,Photon Chat으로) 이름으로 룸을 쉽게 만들어서 OpJoinOrCreateRoom를 이용하여 룸에 입장 할 수 있습니다.

다음 처럼 유일한 이름으로 구성될 수 있습니다:"friendName1 + friendName2 + randomInteger" 누구나 참여할 수 없도록 하려면 다음과 같이 룸이 보이지 않게 생성합니다:

RoomOptions roomOptions = new RoomOptions();
roomOptions.isVisible = false;
lbClient.JoinOrCreateRoom(nameEveryFriendKnows, roomOptions, typedLobby);

JoinOrCreateRoom 은 룸이 존재 하지 않는다면 룸을 생성하게 됩니다. 만약 룸이 가득차 있다면 OpJoin 오퍼레이션은 실패 하므로 OnOperationResponse 을 체크 해보세요.

유일한 userID를 얻었다면 OpFindFriends 를 통하여 친구를 찾을 수 있습니다.

룸에 UserID들을 게시하기

Photon 은 다양한 장소에서 UserID 를 사용합니다. 예를 들어, 플레이어별로 적절한 UserId 를 통해 친구를 찾을 수 있습니다. 룸에서 플레이어들의 UserID를 알 수 있도록 하는 옵션을 Photon 에 추가했습니다. 이 옵션을 이용하려면 룸을 생성할 때 RoomOptions.PublishUserIdtrue 로 설정하시면 됩니다. 클라이언트에서 PhotonPlayer.UserId 를 이용하면 서버는 UserId 를 제공 해주게 됩니다.

노트:

  • UserIDs 는 Photon 의 참여 이벤트에서 플레이어 프로퍼티와 같이 브로드캐스트 됩니다.
  • 클라이언트의 UserID 는 세가지 방식으로 설정 될 수 있습니다:
    1. 연결 전에 클라이언트가 LoadBalancingClient.UserId를 설정 합니다.
    2. 커스텀 인증을 이용한 외부 웹서비스에서 전달된 값으로 클라이언트가 보낸 값을 덮어 쓰게 될 것 입니다.
    3. Photon 은 사용자의 UserID를(GUID) 만들게 되며 명시적으로 지정 하지는 않습니다.
  • 일반적으로 UserID들은 화면에 표시되는 목적이 아닙니다.

매치메이킹 자리 예약

때로 플레이어가 룸에 참여할 때 친구도 역시 참여할 것이라는 것을 알고 있습니다. 자리 예약으로 Photon 은 자리 블록을 통하여 특정 유저에게 자리를 제공하여 매치메이킹에 사용할 수 있습니다. 자리를 예약 하기 위해서는 (JoinRoom, JoinOrCreateRoom, JoinRandomRoomCreateRoom) 메소드내에 expectedUsers 파라미터를 이용 합니다.

누군가가 참여한다는 것을 알고 있으면 UserID 의 배열을 전달합니다. JoinRandomRoom 에 대해서 서버는 충분한 자리가 있는 룸과 참여가 예상되는 플레이어들(룸 안의 모든 액티브와 이미 참여 하고 있는 플레이어들)을 찾을 것 입니다. 서버는 룸 안의 클라이언트를 현재 expectedUsers 로 업데이트 시킬 것이고 클라이언트는 변경 되어야 합니다. 자리 예약을 지원하기 위해 룸 안으로 UserID 를 주는 것을 허용해야 합니다.

유즈 케이스 예:

매치메이킹에서 팀을 지원하기 위해 사용할 수 있습니다:팀의 리더가 실제의 매치메이킹을 수행 합니다. 리더는 룸에 참여할 수 있으며 모든 멤버를 위해서 자리를 예약 합니다. 다른 멤버들은 매치메이킹에 대해서 할 것은 아무것도 없으며 대신에 반복적으로

lbClient.OpFindFriends(new string[1]{leaderUserId}) 를 호출 하면 됩니다. 리더가 룸에 들어 왔을 때 FindFriends 오퍼레이션은 룸의 이름을 나타내고 멤버들이 참여할 수 있습니다.

로비

Photon 은 룸을 "로비"라고 불리는 곳에 룸을 구성하고 있습니다. 디폴트 로비가 있기는 하지만 그때 그때 새로운 로비를 생성할 수 있습니다. 로비는 CreateRoom 에서 로비를 지정 할 때 존재하기 시작 합니다.

룸 처럼 로비에 참여할 수 있습니다. 로비 내에서 클라이언트가 할 수 있는 일은 해당 로비에 있는 룸에만 들어 가는 것이며 아무것도 할 수 없습니다. 로비에서 다른 클라이언트와 소통 할 수 있는 방법이 없습니다.

지금 까지 로비에 참여하지 않도록 독려 하였습니다:

때로는 클라이언트들이 긴 룸 리스트를 얻어 플레이어가 무작위로 하나를 선택해서 플레이를 시작할 수 있습니다. 룸 이름 목록에는 많은 정보가 없습니다. 매치메이킹에 대한 선택권을 플레이어들에게 더 부여하기 위해서는 무작위 매치메이킹에 필터를 사용 합니다. 서버측 무작위 매치메이킹에 사용 되기 때문에 다수의 로비는 여전히 유용합니다.

로비는 이름과 타입으로 식별 됩니다. 이름은 어떤 문자열이 될 수 있으며 로비에는 3가지 타입이 있습니다. 특정한 유즈 케이스에 맞추기 위한 유일한 기능이 각각 존재 합니다.

디폴트 로비 타입

특별한 것이 없는 로비 타입 입니다. 동기적 무작위 매치메이킹에 가장 적합한 타입 입니다. 아마 가장 덜 복잡하고 가장 많이 사용되는 타입 입니다.

예를 들어 권장되는 디폴트 로비(TypedLobby.Default)는 null 이름과 LobbyType.Default 타입 입니다.

SQL 로비 타입

이 로비 타입은 JoinRandomRoom 오퍼레이션에 더 정교한 매치메이킹 필터링에서 널리 사용되고 있는 "클라이언트 상에서의 룸 리스트" 를 대신하는 것 입니다. 완전하게 클라이언트 기반이었던 스킬기반 매치메이킹을 서버측에서 사용 할 수 있습다.

내부적으로 SQL-로비들은 최대 10개까지 특수한 "필터링-프로퍼티"를 가진 SQLite 테이블에서 룸을 나열 합니다. 현재는 이러한 이름은 "C0", "C1" 에서 "C9" 까지 고정 되어 있습니다.

정수형과 스트링형의 값만 허용되며 특정 로비에의 컬럼에 값이 지정되면, 이 컬럼은 해당 타입으로 고정되게 됩니다. 고정된 필터링-프로퍼티 이름에도 불구하고 클라이언트들은 로비에서 어떤것이 필요한 것인지를 정의 해야 합니다. 이러한 룸 프로퍼티들의 값은 언제든지 설정 할 수 있습니다. 다른 프로퍼티들은 평소와 같이 설정될 수 있으나 매치메이킹에는 사용 될 수 없습니다.

예제:

RoomOptions roomOptions = new RoomOptions();
roomOptions.MaxPlayers = expectedMaxPlayers;
// in this example, C0 might be 0 or 1 for the two (fictional) game modes
roomOptions.customRoomProperties = new ExitGames.Client.Photon.Hashtable() { { "C0", 1 } };
roomOptions.customRoomPropertiesForLobby = new string[] { "C0" }; // this makes "C0" available in the lobby
// let's create this room in SqlLobby "myLobby" explicitly
TypedLobby sqlLobby = new TypedLobby("myLobby", LobbyType.SqlLobby);
lbClient.OpCreateRoom(roomName, roomOptions, sqlLobby);

JoinRandomGame 오퍼레이션에 쿼리가 전송될 수 있습니다. 필터링 쿼리는 "C0" .. "C9" 값을 기반으로 한 기본 SQL 문장입니다.

TypedLobby sqlLobby = new TypedLobby("myLobby", LobbyType.SqlLobby);    // same as above
string sqlLobbyFilter = "C0 = 0";   // find a game with mode 0
lbClient.OpJoinRandomRoom(null, expectedMaxPlayers, matchmakingMode, sqlLobby, sqlLobbyFilter);
// more filter variations:
// "C0 = 1 AND C2 > 50"
// "C5 = \"Map2\" AND C2 > 10 AND C2 < 20"

스킬 기반 매치메이킹

SQL-타입의 로비는 나만의 스킬기반 매치메이킹을 구현 할 때 이용 할 수 있습니다.

우선, 룸은 참가할 때 플레이어들이 가지고 있어야 하는 고정된 스킬을 받습니다. 이 값은 변경되지 않아야 하며 변경되면 이 전에 매칭된것은 기본적으로 더 이상 유효 하지 않습니다.

일반적으로 플레이어들은 JoinRandomRoom으로 룸에 입장을 하려고 합니다. 필터는 사용자의 기술을 기반으로 해야 합니다. 클라이언트는 "skill +/- X" 로 룸에 대해서 쉽게 필터 할 수 있습니다.

JoinRandomRoom 은 평소와 같이 즉시 응답을 받지만 곧 바로 룸을 찾을 수 없었다면 클라이언트는 수초간 대기 후에 다시 시도 해야 합니다! 원하는 만큼 요청을 할 수 있습니다. 이중에서 가장 좋은 것: 클라이언트는 시간이 지남에 따라 필터 규칙을 완화 할 수 있습니다.

시간이 경과 후에 필터를 완화 시켜주는 것이 중요 합니다. 그렇습니다: 룸은 드문 스킬을 가진 플레이어를 참여 시킬 수 있으나 분명히 다른 방들에 비해서는 매칭이 어렵게 되므로 누군가와 플레이하기가 힘들 수 있습니다.

최대 편차 및 타임아웃을 정의 할 수 있습니다. 만약 검색된 룸이 없다면 이 클라이언트는 사용자가 가진 스킬로 새로운 룸을 오픈 해야 합니다. 그리고 이 클라이언트는 다른 플레이어들을 기다려야 합니다.

명백히 , 이 흐름은 사용할 수 있는 룸이 적을 때 시간이 걸릴 수 도 있습니다."어플리케이션 통계"를 체크하여 사용할 수 있는 룸이 몇개나 있는지 플레이어가 무작정 기다리지 않도록 할 수 있습니다.

필터를 조정하고 "less than 100 rooms"

당신은 필터와 "100 개 미만의 룸"에 대한 타이밍과 "100에서 1000까지 룸" 의 다른 설정등을 조정 할 수 있습니다.

비동기 무작위 로비 타입

이 로비 타입은 하나의 큰 차이점만 제외 하면 디폴트 로비 타입과 유사합니다: 룸 엔트리는 로비내에 룸이 닫인 후에도 한 시간동안 남아 있습니다(개별 룸 상태는 모든 플레이어가 떠나고EmptyRoomTTL 만료 되었다면 Photon Game 서버에서 제거 됩니다).

이러한 룸은 클라이언트가 수신한 로비 리스트에 보여져야 합니다. 사용할 수 있는 게임에 플레이어를 보여야 할 필요가 있습니다. 모든 경우에 있어서 비동기 매치메이킹 으로 참여 하기 위하여 룸은 오픈된 상태로 있어야 합니다.

이 로비 타입은 비동기 (재)참여가 완전히 동작하기 위해서 webhooks 또는 룸 상태를 보존하는 다른 방법과 조합될 수 있습니다.

다른 매치메이킹 옵션

나만의 매치메이킹을 만들고 싶으면 대부분의 기능이 서버측에서 수행되도록 하시기 바랍니다. 서버에서 클라이언트로의 룸 리스트 갱신 주기는 (~1..2 초)이므로 클라이언트는 얼마나 많은 룸이 있는지 정확히 알 수 없습니다.

수천명의 플레이어가 있을 때는 몇개의 클라이언트가 동시에 "참여" 요청을 전송 할 것 입니다. 룸이 빠르게 채워지면, 플레이어들이 자주 룸 참여에 실패하게 되며 참여까지 걸리는 시간이 점점 더 길어지게 될 것 입니다.

다른 한편으로 서버는 모든 룸을 가득 채우면서 필터링을 준수하며 플레이어들을 완벽하게 분산 시킬 수 있습니다.

다시말하면, 실제 게임이 시작되기 전에 룸을 매칭 공간으로 사용하는 것은 인기있는 게임의 대부분의 경우에 적합 하지는 않습니다.

 기술문서 TOP으로 돌아가기