BackEndMatch 설명

BackEndMatch는 뒤끝서버에 지원하는 뒤끝매치라는 것이다. 이를 통해 매칭을 지원하고 게임에 필요한 데이터를 통해 게임을 진행할 수 있다.

1.매치 서버 구조

매치 서버의 구조를 보면, 로그인 된 유저가 ‘매치 서버’에 접속 한 뒤, 매칭을 신청하는 것까지 진행된다. 매치의 타입은 다양하게 존재하는데, 점수를 기반으로하는 모드, 랜덤 모드, MMR 모드 등 다양하다. 매치를 신청할 때 원하는 매치 타입을 선택하면 된다. 매칭이 시작되고 매칭 중 조건에 맞는 유저가 모두 모이면 매칭이 성사된다. 매칭에 성공하면 매칭 서버에서 접속할 인게임 서버 정보와 접속할 방의 정보들을 송신한다.

< 매치 서버 구조 >

2.인게임 서버 구조

매칭이 성사되면 인게임 서버에 접속되게 된다. 인게임 서버에 접속하면 인게임 방에 접속하게 되고, 접속된 방에서는 유저들의 정보를 주고 받게 된다. 모든 정보를 주고 받고 매칭된 모든 유저가 방에 접속하게 되면 게임이 시작되고, 게임이 진행되고 모든 게임이 끝나고 결과가 나오면 모든 클라이언트는 결과를 서버로 접속해서 서버에서 게임 결과 종합이 완료되면 모든 게임이 종료된다.

< 인게임 서버 구조 >

3.Poll()

클라이언트의 메세지를 서버로 송신하고, 수신한 데이터를 이벤트 형태로 호출시킨다. 항상 메시지를 송수신하기 위해 Poll 함수는 주기적을 호출되어야 한다. 유니티 객체의 Update 함수에서 Poll을 호출하거나 코루틴을 생성하고 해당 코루틴 내에서 주기적으로 호출하면 된다.

    private void Update() 
    {
        Backend.Match.Poll();
    }

Poll 함수를 사용하지 않으면 BackEndMatch를 이용할 수 없다.

4.매칭 서버 접속 요청 및 이벤트

매칭 서버 접속 함수를 호출하면 매칭 서버에 접속을 요청한다.

ErrorInfo errorInfo;
Backend.Match.JoinMatchMakingServer(out errorInfo);

매칭 서버에 접속이 성공/실패했을 때 호출되는 이벤트이다.

Backend.Match.OnJoinMatchMakingServer += (args) => {
    // TODO
};

5.대기방 생성 요청 및 이벤트

대기방을 생성한다.

Backend.Match.CreateMatchRoom();

대기방을 생성하였을 때 호출되는 이벤트 핸들러이다.

Backend.Match.OnMatchMakingRoomCreate += (args) => {
    // TODO
};

6.매칭 신청 요청 및 이벤트

뒤끝 콘솔에서 생성한 매칭을 신청한다.

Backend.Match.RequestMatchMaking(matchType, modeType, inDate);

매칭 신청 요청에 따른 이벤트

Backend.Match.OnMatchMakingResponse += (args) => {
    // TODO
};

ArgumentCase

매칭 신청에 성공했을 때

ErrInfo : ErrorCode.Match_InProgress

매칭이 성사되었을 때

ErrInfo : ErrorCode.Success
MatchCardIndate : 성사된 매칭 카드 inDate
RoomInfo : 인게임 서버 및 입장할 방의 정보

매칭 신청을 취소했을 때

ErrInfo : ErrorCode.Match_MatchMakingCanceled

잘못된 매치 타입으로 매칭을 신청했을 때

ErrInfo : ErrorCode.Match_InvalidMatchType

잘못된 매치 모드 타입으로 매칭을 신청했을 때

ErrInfo : ErrorCode.Match_InvalidModeType

잘못된 요청을 했을 때

ErrInfo : ErrorCode.InvalidOperation
Reason : 에러 상황에 대한 이유

매칭 신청 요청을 2번 이상 보낸 경우

ErrInfo : ErrorCode.InvalidOperation
Reason : Already matchmaking in-progress.

방장이 아닌 유저가 매칭을 신청했을 때

ErrInfo : ErrorCode.InvalidOperation
Reason : You are not owner of room.

방장이 아닌 유저가 매칭을 취소했을 때

ErrInfo : ErrorCode.InvalidOperation
Reason : You are not owner of room.

대기방에 허용된 팀 인원보다 많은 인원이 존재할 경우 (ex. 2:2 팀전에서 대기방에 3명 이상의 유저가 존재)

ErrInfo : ErrorCode.Match_Making_InvalidRoom
Reason : There are currently more squad members than are supported.

대기방에 2명 이상의 유저가 존재하는데 1:1, 개인전 매칭을 신청한 경우

ErrInfo : ErrorCode.InvalidOperation
Reason : Squad does not support OneOnOne or Melee mode.

매칭이 성사되었으나 서버에서 인게임 룸 생성에 실패했을 경우 (다시 매칭을 신청해야 합니다.)

ErrInfo : ErrorCode.Match_MatchMakingCanceled
Reason : FDM 코드 리턴

7.매치 타입

매칭 신청을 하기 위해 미리 뒤끝 콘솔에 생성해 둔 매치를 통해 매칭을 진행할 수 있다.

< 뒤끝 콘솔의 매치 관리 >
매칭 카드 정보 조회

Backend.Match.GetMatchList(); // 동기
Backend.Match.GetMatchList( callback => {
  // 이후 처리
});//비동기

조회 결과

{ 
    rows:
    [ 
        { 
          inDate: {"S" : "2020-08-04T09:24:14.807Z"},
          matchTitle : {"S", "매치타이틀"},
          enable_sandbox : {"BOOL" : false}
          matchType : {"S" : "mmr"},
          matchModeType : {"S" : "OneOnOne"},
          matchHeadCount : {"N" : "2"},
          enable_battle_royale : {"BOOL" : false},
          match_timeout_m : {"N" : "60"},
          transit_to_sandbox_timeout_ms : {"N" : "10000"},
          match_start_waiting_time_s : {"N" : "15"}
          match_increment_time_s : {"N" : "10"},
          maxMatchRange : {"N" : "5000"},
          increaseAndDecrease : {"N" : "1000"},
          initializeCycle : {"S" : "week"},
          defaultPoint : {"N" : "1000"},
          savingPoint :
            // 1:1, 팀전 점수 증감 값 예
            {"M":{"defeat":{"N":"-5"},"victory":{"N":"5"},"draw":{"N":"0"}}}
            // 개인전 점수 증감 값 예
            {"L":[{"M":{"1":{"S":"1"}}},{"M":{"2":{"S":"1"}}},{"M":{"3":{"S":"1"}}},{"M":{"4":{"S":"1"}}}]} 
        },
        { 
          inDate: [object], // 매칭 카드의 키값
          matchTitle : [object], // 콘솔에서 설정한 매치 이름
          enable_sandbox : [object], // 샌드박스 모드 활성화 여부
          matchType : [object],  // 매치 타입
          matchModeType : [object], // 매치 모드 타입
          matchHeadCount : [object], // 인원수
          enable_battle_royale : [object], // (optional. 개인전) 배틀로얄 활성화 여부
          match_timeout_m : [object], // 게임방 최대 유지 시간
          transit_to_sandbox_timeout_ms : [object], // 샌드박스 모드가 활성화된 경우 샌드박스 모드로 전환되는 시간
          match_start_waiting_time_s : [object], // 모든 유저가 게임방에 입장한 후 게임 시작 메시지가 리턴되기까지 걸리는 시간
          match_increment_time_s : [object], // (optional. 포인트, MMR) 매칭되지 않았을 때 매칭 범위를 늘리는 기준 시간
          maxMatchRange : [object], // (optional. 포인트, MMR) 최대 매칭 범위
          increaseAndDecrease : [object],  // (optional. 포인트, MMR) 최대 매칭 범위 증가 폭
          initializeCycle : [object], // 전적/점수 초기화 주기
          defaultPoint : [object], // (optional. 포인트) 최초 시작 포인트
          savingPoint : [object] // (optilnal. 포인트, MMR) 승/패/등수 달성 시 증감 포인트 설정값
        }  
    ],
}

8.인게임 서버 접속 요청 및 이벤트

인게임 서버에 접속을 시도한다. 인게임 서버 접속 함수의 리턴이 true인 것은 서버 접속에 성공한 것이 아닌 단순히 서버와 소켓이 연결된 것이다. 실제 서버 연결은 인게임 서버에서 유저 인증을 완료한 후 이루어지며, 인게임 서버의 접속 성공/실패 여부는 이벤트를 통해 확인할 수 있다.

string serverAddress;
ushort serverPort;

OnMatchMakingResponse += (args) => // serverAddress와 serverPort 확인하는 곳
{
    string serverAddress = args.RoomInfo.m_inGameServerEndPoint.m_address;
    ushort serverPort = args.RoomInfo.m_inGameServerEndPoint.m_port;
}

void JoinInGameServer() // 임의의 함수
{
    bool isReconnect = true;
    ErrorInfo errorInfo = null;

    if(Backend.Match.JoinGameServer(serverAddress, serverPort, isReconnect, out errorInfo) == false)
    {
        // 에러 확인
        return;
    }
}

인게임 서버에 접속 실패/성공했을 때 호출되는 이벤트이다.

Backend.Match.OnSessionJoinInServer += (args) => {
    // TODO
};

9.게임방 접속 요청 및 접속 이벤트

게임방에 접속한다. 반드시 인게임 서버 접속 후 호출되어야 한다. 매칭 서버와 대기방과 인게임 서버의 게임방은 분리되어 있는 별개의 개념이다.

Backend.Match.JoinGameRoom(roomToken);

유저가 게임방 접속에 성공했을 때 입장한 유저에게만 최초 1회 호출되는 이벤트 핸들러이다. 자신을 포함하여 현재 게임방에 접속해 있는 유저들의 세션 정보와 매칭 기록이 포함되어 있다.

Backend.Match.OnSessionListInServer += (args) => {
    // TODO
};

ArgumentCase

유저가 게임방에 입장했을 때(입장한 유저에게만 호출됨)

ErrInfo : ErrorCode.Success
RoomInfo : “룸정보”
GameRecords : 현재 접속한 유저들의 정보

유저가 게임방 접속에 실패했을 때

호출되지 않습니다.

10. 게임 시작 이벤트

게임방에 모든 유저가 접속하여도 바로 게임을 진행항 수 없다. 모든 유저가 게임방에 접속한 이후 콘솔에서 설정한 매치 시작 대기시간을 지난 이후에 모든 유저에게 게임 시작 이벤트가 호출된다.

Backend.Match.OnMatchInGameStart += () =>
    // TODO
};

11.데이터 송수신 및 이벤트

데이터 송수신은 바이트 배열을 통해 송수신되며, 송신된 데이터는 서버에서 현재 게임방에 참여한 모든 클라이언트에게 브로드캐스팅된다.

Backend.Match.SendDataToInGameRoom(data); //송신

수신 이벤트

Backend.Match.OnMatchRelay += (args) => {
    // TODO
};

ArgumentCase

바이너리 데이터를 수신 받았을 때

From : 보낸 유저 세션 정보
BinaryUserData : 보낸 데이터

12.게임 결과 처리 및 이벤트

게임의 결과를 서버로 전송한다. 게임 결과 메시지를 서버로 보내고 서버에서 결과 종합을 완료한 경우 게임 결과 이벤트와 인게임 서버 접속 종료 이벤트가 함께 호출된다. 게임의 결과는 모든 유저가 보내야 결과가 종합되어야 게임이 종료 된다.

// 1:1
MatchGameResult matchGameResult = MatchGameResult();
matchGameResult.m_winners = new List<SessionId>();
matchGameResult.m_losers = new List<SessionId>();

matchGameResult.m_winners.Add("승자 세션 ID");
matchGameResult.m_losers.Add("패자 세션 ID");
// --------------------

// 팀전
MatchGameResult matchGameResult = MatchGameResult();
matchGameResult.m_winners = new List<SessionId>();
matchGameResult.m_losers = new List<SessionId>();

foreach(var session in winnerTeam)
{
    // 순서는 무관합니다.
    matchGameResult.m_winners.Add(session);
}

foreach(var session in loserTeam)
{
    // 순서는 무관합니다.
    matchGameResult.m_losers .Add(session);
}
// --------------------

// 개인전
MatchGameResult matchGameResult = MatchGameResult();
foreach(var session in rank)
{
    // 1등부터 차례대로 추가해야 합니다.
    matchGameResult.m_winners.Add(session);
}
// --------------------

// 서버로 결과 전송
Backend.Match.MatchEnd(matchGameResult);

결과 처리 이벤트

Backend.Match.OnMatchResult += (args) => {
    // TODO
};

ArgumentCase

결과 종합 성공

ErrInfo : ErrorCode.Success

결과 종합 실패 (서버에서 결과 종합을 실패한 경우)

ErrInfo : ErrorCode.Exception
Reason : 결과 종합 실패 이유 (혹은 FDM 코드 리턴)

게임 시작 실패 (룸 생성 후 모든 유저가 게임에 접속하지 않은 경우)

ErrInfo : Match_InGame_Timeout
Reason : Some gamers are not connected. (0)

결과 종합 실패 (모든 유저가 결괏값을 서버로 전송하지 않은 경우)

ErrInfo : Exception
Reason : error: Success, status: 400, reason: {“errorCode”:”BadParameterException”,”message”:”bad headCount, 잘못된 headCount 입니다”,”statusCode”:400}

콘솔에서 결과 처리를 기본 모드로 설정한 경우

한 유저가 결과 종합 메시지를 서버로 전송한 후 15초 이내에 모든 유저가 결과 종합 메시지를 서버로 전송하지 않은 경우 해당 에러가 발생할 수 있습니다.
모든 유저가 게임 결과를 보내지 않은 경우 해당 게임은 무효 처리 됩니다.

결과 종합 실패 (게임에 참여한 유저의 수와 결과에 포함된 유저 수가 다른 경우)

ErrInfo : Exception
Reason : error: Success, status: 400, reason: {“errorCode”:”BadParameterException”,”message”:”bad headCount, 잘못된 headCount 입니다”,”statusCode”:400}

결과 종합 실패 (결과에 포함되어 있는 승/패 유저 리스트와 실제 팀 유저들이 일치하지 않는 경우)

ErrInfo : Exception
Reason : error: Success, status: 400, reason: {“errorCode”:”BadParameterException”,”message”:”bad invalid team infomation, 잘못된 invalid team infomation 입니다”,”statusCode”:400}

게임 시간 초과 (콘솔에서 설정한 매치 제한 시간을 초과한 경우)

ErrInfo : Match_InGame_Timeout
Reason : Timeout

올바르지 않은 결괏값을 서버로 보낸 경우 (결괏값을 보내지 않거나, 일부 유저만 결괏값에 포함시키거나 등…)

ErrInfo : ErrorCode.Exception
Reason : FDM: “에러FDM 코드”

2부에서 구현 진행