Matchmaking

Note

Stability: 2 - Unstable

Overview

Hydra’s goal is to support a wide range of gameplay, so we offer multiple solutions to fit different game types. This is especially true for matchmaking. Currently, Hydra offers two types of matchmaking: fluid and fixed.

Matchmaking Criteria

At the center of either matchmaking style is the Matchmaking Criteria. Criteria allows you to supply parameters to the matchmaking process. When looking for matches, you specify the criteria to use, which controls what players are brought into a match. You can have multiple criteria to fit different styles of matchmaking you may use throughout your game.

Creating & Editing

All matchmaking criteria are configurable within the Hydra developer dashboard. From the dashboard:

  1. Select the Project and Environment that you would like to set up matchmaking criteria for.
  2. Select Matchmaking from the left sidebar (under Multiplayer Config).
  3. Click the “Create new spec” button. You are then presented with a list of options that you’ll need to configure.
  4. Once you save the criteria, it is available for matchmaking.
  5. At anytime, you can return to the Matchmaking page (steps 1 & 2 above) to edit existing matchmaking criteria. Click the criteria you want to change, and make your adjustments.

Configuration

We provide a number of configurable options for matchmaking criteria:

Name :
Free-form text field used to display to users if necessary.
Slug :
Human-readable unique identifier for your criteria. The slug will be pre-populated for you based on your criteria name, but can also be edited at time of creation. A slug cannot be edited after creation.
Match Type :
The match template that should drive the criteria.
Timeout : (seconds)
Fixed Matches Only. The time to wait before canceling a matchmaking request if no match is found.
Matchmaking Rules:

The rules that dictate the players that make up a match.

You can select how to group multiple rules.

All :
This rule is satisfied if all of the nested rules are true.
Any :
This rule is satisfied if any of the nested rules are true.
None :
This rule is satisfied if none of the nested rules are true.

You can then select the operation for each rule.

equal :

Makes sure that all players have the same value for the given field.

field : string
The field to use for this rule.
intersection :

Makes sure that all players share one or more values for the given field.

field : string
The field to use for this rule.
union :

Makes sure that players share one or more values for the given field with at least one other player.

field : string
The field to use for this rule.
one of each :

Makes sure that for every value given, there is one player whose field equals that value.

field : string
The field to use for this rule.
values : comma separated list
The list of values that must be represented in a match.
range :

Makes sure that the match is made up of players whose field falls within the given range.

field : string
The field to use for this rule.
range : integer
The allowed range for the given field.

Note: As you can see, these rules are logic based (true or false). We will be offering more fuzzy rules soon.

You can then select where the rule should get the value for the given field.

in profile :
Match against profile data of players being considered for the match.
in request :
Match against data submitted to Hydra in the matchmaking request (this would typically be options selected by player in the game UI).

Fluid Matches

The goal of fluid (also known as quick) matches is to offer a simple and fast way to get your users into a match with other players. When you request to join a fluid match you are guaranteed to be in a match that fits the given criteria (if a match is unavailable, a new match is created). This style of matchmaking also allows you to list available matches that fit a specific criteria. You can use this list to offer a list of matches to the user. This style allows a match to exist while a search for other players continues, and allows players to come and go.

Listing Matches

You can request available matches for a given criteria. The data parameter can be null if your criteria does not use request data. There are also additional overloads of these functions if you need to specify the realtime cluster the match should be in.

  • AGPromise* matchesPromise = [client.matchMakingService list:criteriaSlug data:data];
    [matchesPromise when:^(NSArray* matches) {
        // ...
    }];
    
  • client.MatchMaking.List(criteriaSlug, data, delegate(List<Match> matches, Request request)
    {
        // ...
    });
    
  • client.getMatchMakingService().list(criteriaSlug, data, new ObjectListListener<Match>() {
        @Override
        public void objectReceived(List<Match> object, Response r) {
            // ...
        }
    });
    
  • client->getMatchmakingService().list(criteriaSlug, data, [](std::vector<std::shared_ptr<Match>> matches, Request* request) {
        // ...
    });
    
  • Documentation coming soon.

Joining Matches

You can join the first available match for a given criteria. The data parameter can be null if your criteria does not use request data. There are also additional overloads of these functions if you need to specify the realtime cluster the match should be in.

  • AGPromise* joinPromise = [client.matchMakingService join:criteriaSlug data:data];
    [joinPromise when:^(AGMatch* match) {
        // ...
    }];
    
  • client.MatchMaking.Join(criteriaSlug, data, delegate(Match match, Request request)
    {
        // ...
    });
    
  • client.getMatchMakingService().join(criteriaSlug, data, new ObjectListener<Match>() {
        @Override
        public void objectReceived(Match object, Response r) {
            // ...
        }
    });
    
  • client->getMatchmakingService().join(criteriaSlug, data, [](std::shared_ptr<Match> match, Request* request) {
        // ...
    });
    
  • Documentation coming soon.

You can also join an existing match for a given criteria. The data parameter can be null if your criteria does not use request data.

  • AGPromise* joinPromise = [client.matchMakingService joinExisting:criteriaSlug existingMatchId:matchKey data:data];
    [joinPromise when:^(AGMatch* match) {
        // ...
    }];
    
  • client.MatchMaking.JoinExisting(criteriaSlug, matchId, data, delegate(Match match, Request request)
    {
        // ...
    });
    
  • client.getMatchMakingService().joinExisting(criteriaSlug, matchId, data, new ObjectListener<Match>() {
        @Override
        public void objectReceived(Match object, Response r) {
            // ...
        }
    });
    
  • client->getMatchmakingService().joinExisting(criteriaSlug, matchId, data, [](std::shared_ptr<Match> match, Request* request) {
        // ...
    });
    
  • Documentation coming soon.

Fixed Matches

The goal of fixed matches is to offer a higher quality of players for a match than fluid matches would. When you submit a matchmaking request, you will not be placed in a match right away. Instead, you will be placed in a pool of available players. The matchmaking process will then analyze all of the current matchmaking requests and find the best grouping of players. There is no way to offer a list of available matches based on this type of matchmaking. After you submit the matchmaking request, you will be notified when the process has found you a match. This style of matchmaking suits games where it wouldn’t make sense to let players join or leave matches.

Requesting Matches

You can kick off a fixed matchmaking request via the Submit function. This will return a Matchmaking Request object which you can use to track the status of your request. The data parameter can be null if your criteria does not use request data. There are also additional overloads of these functions if you need to specify the realtime cluster the match should be in.

  • AGPromise* submitPromise = [client.matchMakingService submit:criteriaSlug data:data];
    [submitPromise when:^(AGMatchMakingRequest* matchMakingRequest) {
        // ...
    }];
    
  • client.MatchMaking.Submit(criteriaSlug, data, delegate(MatchMakingRequest matchmakingRequest, Request request)
    {
        // ...
    });
    
  • client.getMatchMakingService().submit(criteriaSlug, data, new ObjectListener<MatchMakingRequest>() {
        @Override
        public void objectReceived(MatchMakingRequest matchMakingRequest, Response response) {
            // ...
        }
    });
    
  • client->getMatchmakingService().submit(criteriaSlug, data, [](std::shared_ptr<MatchMakingRequest> matchmakingRequest, Request* request) {
        // ...
    });
    
  • Documentation coming soon.

Canceling Requests

You can cancel a pending matchmaking request via the Cancel function.

  • AGPromise* cancelPromise = [client.matchMakingService cancelByRequest:matchmakingRequest];
    [cancelPromise when:^(AGRequest* request) {
        // ...
    }];
    
  • client.MatchMaking.Cancel(matchmakingRequest, delegate(Request request)
    {
        // ...
    });
    
  • client.getMatchMakingService().cancel(matchmakingRequest, new ResponseListener>() {
        @Override
        public void responseReceived(Response response) {
            // ...
        }
    });
    
  • client->getMatchmakingService().cancel(matchmakingRequest, [](Request* request) {
        // ...
    });
    
  • Documentation coming soon.

Handling Events

You can subscribe to the following matchmaking request events:

complete :
The matchmaking request completed successfully and the player has joined a match.
tick :
The matchmaking request is still active, but has not found a match yet. This should be triggered continuously.
timeout :
The matchmaking request failed to find any matches within the allotted time.
cancel :
Fixed Matches Only. The matchmaking request was canceled.
  • @interface MatchMakingRequestDelegate : NSObject <AGMatchMakingRequestDelegate>
    
    @end
    
    @implementation MatchMakingRequestDelegate
    
    - (void)tick:(AGMatchMakingRequest*)request {
        // ...
    }
    
    - (void)complete:(AGMatchMakingRequest*)request {
        // ...
    }
    
    - (void)timeout:(AGMatchMakingRequest*)request {
        // ...
    }
    
    - (void)cancel:(AGMatchMakingRequest*)request {
        // ...
    }
    
    @end
    
    [matchMakingRequest setMatchMakingRequestDelegate:matchmakingRequestDelegate];
    
  • {
        // ...
        matchMakingRequest.Complete += MatchmakingComplete;
        matchMakingRequest.Tick += MatchmakingTick;
        matchMakingRequest.Timeout += MatchmakingTimeout;
        matchMakingRequest.Cancel += MatchmakingCancel;
        // ...
    }
    
    void MatchmakingComplete(MatchMakingRequest mmRequest)
    {
        // ...
    }
    
    void MatchmakingTick(MatchMakingRequest mmRequest)
    {
        // ...
    }
    
    void MatchmakingTimeout(MatchMakingRequest mmRequest)
    {
        // ...
    }
    
    void MatchmakingCancel(MatchMakingRequest mmRequest)
    {
        // ...
    }
    
  • matchMakingRequest.setListener(new MatchMakingRequest.MatchMakingRequestListener() {
        @Override
        public void complete(MatchMakingRequest mmRequest) {
            // ...
        }
    
        @Override
        public void tick(MatchMakingRequest mmRequest) {
            // ...
        }
    
        @Override
        public void timeout(MatchMakingRequest mmRequest) {
            // ...
        }
    
        @Override
        public void cancel(MatchMakingRequest mmRequest) {
            // ...
        }
    });
    
  • matchMakingRequest->Complete.add("handler1", [](std::shared_ptr<MatchMakingRequest> mmRequest) {
        // ...
    });
    
    matchMakingRequest->Tick.add("handler1", [](std::shared_ptr<MatchMakingRequest> mmRequest) {
        // ...
    });
    
    matchMakingRequest->Timeout.add("handler1", [](std::shared_ptr<MatchMakingRequest> mmRequest) {
        // ...
    });
    
    matchMakingRequest->Cancel.add("handler1", [](std::shared_ptr<MatchMakingRequest> mmRequest) {
        // ...
    });
    
  • Documentation coming soon.

Table Of Contents

Previous topic

Matches

Next topic

Realtime Networking