Gamelift Matchmaking Implementation

Throughout the gamelift development guide matchmaking is mentioned as an example service to make use of the API. I plan to implement this myself, but I thought I’d ask some general questions here to maybe save some time and prevent myself from going down the wrong path, ideally I don’t want to waste resources or use the wrong service when there are better options.

  1. Assuming I have some implementation of player rating, ELO, etc, what would be the best way to match players of similar skill together? Would I create game placement queues for different skill brackets? Would I just place individual games with player skill parameters?

  2. How should the matchmaking mechanism work? I don’t want players creating games, players only have the option to join games, so my basic thought is it to attempt to search for a game within the search parameters (similar skill level), and if none are found attempt to make a game placement request and join the queue. Is this how it should work or is there a better way?

  3. Should I use another Amazon service to implement the matchmaking or can this be done from the client itself safely and efficiently.

  4. This isn’t really a question, but considering how popular this type of feature is, would amazon ever consider implementing an ELO/Trueskill type matchmaking feature built in to gamelift or as a standalone amazon service?

Hi
@Heretix

We
have a blog post on the way that goes into how to create a matchmaking process
using AWS services, it is going through our review process and I hope that it
will be up on the GameDev Blog soon, I will update this post as soon as it’s
up.

In
the meantime, let’s have a look at each part of your question below:

In order to create the most efficient grouping of players, I would recommend
creating a process that iterates over players that are waiting to join a game
and then group based on skill level. Grouping in this way enables you to match
on as many rules as you need before getting the group ready to start a game
session.

This
example Python script shows how you might check a data store for waiting
players (in this case it’s checking AWS DynamoDB) and group them based on
player skill. The variable match_size determines the size of the group needed
and this is set to a value that is suitable for your game sessions.

        def get_unmatched_players():
table = dynamodb.Table(table_name)
response = table.scan(
FilterExpression=Attr('MatchStatus').eq('Open')
)
players = response['Items']
print("Number of players waiting for matches: " + str(len(players)))
return players
def create_groups(players):
print('Creating Groups')
groups = []
# Sort players by skill
sorted(players, key=lambda player: player['Skill'])
# Group players into match sized groups
while (len(players) >= match_size):
new_group = {'Players': []}
for i in range(0, match_size):
new_group['Players'].append(players.pop(0))
groups.append(new_group)
print("Number of groups created: " + str(len(groups)))
return groups

Once
you have a group of players ready to start a game, you can call StartGameSessionPlacement to GameLift, this requests that a
server session be found for the gams session. The game session requests need to
be placed into queues which refer to fleets that are hosting your game servers,
more information on setting up queues can be found here.

This
code snippet shows an example game session request, the start_game_placement
function accepts a queue name, this is defined by you in your GameLift queue
configuration. GameLift requires a unique ID for the placement. You’ll use this
ID to track the status of the placement request, the ID is defined by you and
can be anything unique this example uses a UUID which is passed back to the
caller for further processing.

    def start_game_placement(queue_name, group):
print("Starting Game Session Placement")
placement_id = str(uuid.uuid4())
response = gamelift.start_game_session_placement(
PlacementId=placement_id,
GameSessionQueueName=queue_name,
GameProperties=[
{
'Key': 'Skill_Level',
'Value': 'Highest'
},
],
MaximumPlayerSessionCount=match_size,
GameSessionName='My Matched MP Game',
DesiredPlayerSessions=[
for player in group['Players']:
{
'PlayerId': player['PlayerId'],
'PlayerData': 'Skill value: ' + player['Skill']
},
]
)
print("Game Session Status: " + response['GameSessionPlacement']['Status'])
return placement_id

This
operation will return a status of PENDING until the placement request has been
SUCCESSUL, at this point a GameSesionPlacement
object is returned which contains the connection details that the clients will
use to connect to the game. The status can be checked using DescribeGameSessionPlacement.

By grouping and assigning players to session descried in point 1 we will not be
allowing players to initiate the creation of new games, they will only be able
to attempt to join a game. The matchmaking process handles the grouping and
GameLift will control the allocation/creation of game session depending on your
defined scaling rules and session availability.

I would recommend limiting the responsibilities that the clients have to making
requests to join a game session and connecting to an assigned game. It is
generally preferable to have a single matchmaking authority in a scenario where
matching based on rules such as skill level are required. This also has the
advantage of keeping the level of permissions needed by the client as low as
possible, and by abstracting matchmaking logic from the clients it reduces the
opportunity for cheating via the client. The snippets above actually run in AWS
Lambda and are triggered every second to check a DynamoDB database and perform
the matchmaking logic, once this is complete GameLift takes over to assign the
sessions, manage the overall infrastructure and provide this back to the
clients, there are many options for running matchmaking processes in the cloud,
this is one example that requires very little server maintenance as it uses AWS
managed services in each step.

Thanks for the feedback about adding ELO/Trueskill matchmaking to GameLift. I
have filed a feature request on your behalf. Other users adding their votes and
+1s on the forums here helps us gauge the relative demand for features and can
influence the timeline.

I hope this helps to answer
your questions.

Just to add: Other than skill, sometimes you may want to pay attention to the ping of the player to make sure latency between players isn’t too high, and also pay attention to the amount of time waiting for a room. The more time they are waiting for a room, you may decide to lower the ping or skill match requirements.

Thank you for taking the time to reply, It is clearer now that the game placement queues are queues meant specifically for allocating game servers and how a matchmaking service would feed into that. My game only requires 2 players per server instance and I guess my general concern is finding the MOST efficient way to go about it. I look forward to the blog!

+1. I am eagerly awaiting the blog on matchmaking using AWS services!

Has this matchmaking post been published? I’d believe that the matchmaking algorithm would need to happen server side, for example in the case of ELO matching.

Client A requests a session. Client B request a session. The GameLift matchmaking service searches the players by region, latency etc but also adds in a custom algorithm (Lambda style?) that tries to match players close in ELO ranking and then if it connects client A and B, notifies them as such.

Hi @peterc

Do you think table.scan method is scalable approach to find active players list? what do you think for elastic cache for redis for active players? My game only requires 2 players per server instance.

        def get_unmatched_players():
table = dynamodb.Table(table_name)
response = table.scan(
FilterExpression=Attr('MatchStatus').eq('Open')
)
#rest of the code