Skip to main content

Use the SDK for dedicated server matchmaking - Quick match with dedicated servers - (Unity module)

Last updated on June 5, 2024

Unwrap the wrapper

After setting up a Match Pool, you will call the AccelByte Gaming Services (AGS) Game SDK for dedicated server (DS) matchmaking. This is done in the MatchmakingSessionDSWrapper class in the StartDSMatchmaking function to initiate the matchmaking process using a dedicated server, since you will use the Match Pool name you set up previously with the dedicated server in its Session Template.

Implement dedicated server matchmaking

You will continue the dedicated server matchmaking implementation in the MatchmakingSessionDSWrapper_Starter.cs file.

  1. You need to create a matchmaking ticket based on the Match Pool name. MatchmakingSessionDSWrapper_Starter.cs is a subclass of MatchmakingSessionWrapper, so you don't an instance to get the game client event. Since you will use dedicated server as the gameplay sever type, the game client needs the game server. The server coexists in this project, and the UNITY_SERVER defined symbols are defined when the server build settings are enabled in the Unity Editor Build Settings.

    private void Start()
    {
    #if UNITY_SERVER
    GameManager.Instance.OnRejectBackfill += () => { isGameStarted = true; };
    GameManager.Instance.OnGameStateIsNone += () => { isGameStarted = false; };
    #endif
    }
    Important

    Anonymous functions that listen to GameManager.Instance.OnRejectBackfill event to change the isGameStarted flag are needed because the server should reject any backfill proposal when the game starts.

  2. When matchmaking starts, you will call the StartMatchmaking function in MatchmakingSessionDSWrapper. You also need to check whether the game is set up for a local dedicated server or a cloud dedicated server. Modify MatchmakingSessionDSWrapper_Starter.StartDSMatchmaking as follows:

    protected internal void StartDSMatchmaking(string matchPool)
    {
    ConnectionHandler.Initialization();
    StartMatchmaking(matchPool, ConnectionHandler.IsUsingLocalDS());
    }
  3. You will handle the ticket creation status in the OnStartMatchmakingComplete function in MatchmakingSessionDSWrapper_Starter. Once matchmaking ticket creation succeeds, you will fire OnStartMatchmakingSucceedEvent, the event that will be listened for by the UI. Modify OnStartMatchmakingComplete in MatchmakingSessionDSWrapper_Starter as follows:

    private void OnStartMatchmakingComplete(Result<MatchmakingV2CreateTicketResponse> result)
    {
    if (!result.IsError)
    {
    matchTicket = result.Value.matchTicketId;
    OnStartMatchmakingSucceedEvent?.Invoke(matchTicket);
    }
    else
    {
    OnStartMatchmakingFailed?.Invoke();
    }
    }
  4. Since you already listen for the on match found event, when the match is found you will join the found match session. Once a match is found, you still need to listen to the on join session complete event and then try to join the game session of the match. Modify the OnJoiningMatch in MatchmakingSessionDSWrapper_Starter as follows:

    private void OnJoiningMatch(string sessionId)
    {
    isOnJoinSession = true;
    JoinSession(sessionId);
    }
  5. MatchmakingSessionWrapper will listen to the on joined match session event, and also to the dedicated server available (ready to receive a client connection) event. Once a dedicated server is available, you will fire an event that will be listened to by the UI to start the connection to the dedicated server. Modify OnSessionDSUpdate in MatchmakingSessionDSWrapper_Starter as follows:

    private void OnSessionDSUpdate(Result<SessionV2DsStatusUpdatedNotification> result)
    {
    if (!result.IsError)
    {
    var session = result.Value.session;
    var dsInfo = session.dsInformation;
    switch (dsInfo.status)
    {
    case SessionV2DsStatus.AVAILABLE:
    if (!isFired)
    {
    isFired = true;
    OnDSAvailableEvent?.Invoke(session);
    }
    break;
    case SessionV2DsStatus.FAILED_TO_REQUEST:
    BytewarsLogger.LogWarning($"{dsInfo.status}");
    OnDSFailedRequestEvent?.Invoke();
    break;
    default:
    BytewarsLogger.Log($"{dsInfo.status}");
    break;
    }
    }
    else
    {
    Debug.Log($"{result.Error.Message}");
    }
    }

Handle Backfill

Your game server might not always have the maximum number of players. To fill your game server with new players, you can implement backfill during matchmaking.

  1. Define a variable called serverDSHub that will store any functionalities related to DS Hub notifications. Then, you need to define matchmakingV2Server that will store functionality about accepting and rejecting backfill proposals. In the Awake() function, add the following code:

    private void Awake()
    {
    base.Awake();
    #if UNITY_SERVER
    matchmakingV2Server = MultiRegistry.GetServerApiClient().GetMatchmakingV2();
    serverDSHub = MultiRegistry.GetServerApiClient().GetDsHub();
    #endif
    }
  2. From the game server side, it is required to connect to the DS Hub to subscribe to any notifications from AccelByte Gaming Services (AGS). The connection to DS Hub has been done in ArmadaV3Wrapper.cs. The instance of the class is instantiated in the MultiplayerDSEssentialsWrapper and referenced in the Start function of MatchmakingSessionDSWrapper_Starter. You subscribed to notifications from AGS in the Start() function previously. To subscribe to additional notifications, you will add some additional code in the MatchmakingSessionDSWrapper_Starter class. Subscribe to two events:

    • MatchmakingSessionDSWrapper_Starter.MatchMakingServerClaim() will listen if a server is claimed and assigned to a session.
    • MatchmakingSessionDSWrapper_Starter.BackFillProposal() which listen to backfill proposals.
  3. Modify MatchmakingSessionDSWrapper_Starter.MatchMakingServerClaim() as follows:

    public void MatchMakingServerClaim()
    {
    serverDSHub.MatchmakingV2ServerClaimed += result =>
    {
    if (!result.IsError)
    {
    var serverSession = result.Value.sessionId;
    GameData.ServerSessionID = serverSession;
    BytewarsLogger.Log($"Server Claimed and Assigned to sessionId = {serverSession}");
    }
    else
    {
    BytewarsLogger.LogWarning($"Failed to get server claim event from server");
    }
    };
    }
  4. Modify MatchmakingSessionDSWrapper_Starter.BackFillProposal() as follows:

    private void BackFillProposal()
    {
    serverDSHub.MatchmakingV2BackfillProposalReceived += result =>
    {
    if (!result.IsError)
    {
    BytewarsLogger.Log($"BackFillProposal");

    if (!isGameStarted)
    {
    OnBackfillProposalReceived(result.Value, isGameStarted );
    BytewarsLogger.Log($"Start back-filling process {result.Value.matchSessionId}");

    }
    else
    {
    OnBackfillProposalRejected(result.Value);
    }
    }
    else
    {
    BytewarsLogger.LogWarning($"BackFillProposal {result.Error.Message}");
    }
    };
    }
  5. Create a function to accept and reject the backfill proposal. Open the MatchmakingSessionDSWrapper_Starter and modify OnBackfillProposalReceived as follows to accept backfill:

    private void OnBackfillProposalReceived(MatchmakingV2BackfillProposalNotification proposal, bool isStopBackfilling)
    {
    matchmakingV2Server.AcceptBackfillProposal(proposal, isStopBackfilling, result =>
    {
    if (!result.IsError)
    {
    BytewarsLogger.Log($"Back-filling accepted {!isStopBackfilling}");
    }
    });
    }
  6. To reject the backfill proposal, modify OnBackfillProposalRejected as follows:

    private void OnBackfillProposalRejected(MatchmakingV2BackfillProposalNotification proposal)
    {
    matchmakingV2Server.RejectBackfillProposal(proposal, true, result =>
    {
    if (!result.IsError)
    {
    BytewarsLogger.Log($"Back-filling rejected - Game already started");
    }
    });
    }
  7. Compile to make sure there are no errors.

Resources