Download and review the turn-based multiplayer game code samples in the
samples page.

You should also familiarize yourself with the best practices described in
Quality Checklist.

Starting a match

To begin a turn-based match, your game can prompt players to select how they
want to be matched to other participants or build the match using some default
criteria. Play Games services uses the match configuration data from your
game to return a TurnBasedMatch
object to your game; every time a participant performs an action, such as taking a turn, the game
notifies the other participants via the
OnTurnBasedMatchEventCallback
or OnMultiplayerInvitationEventCallback.

To start a match, follow these steps:

In your app, gather specifications for the type of turn-based match that the
player wants to play and who can participate in the match.

Creates a new turn-based match object, or loads an existing match that meets
the user's criteria if auto-matching is requested. If auto-matching is requested,
the match returned will be either a new match or an existing match where other
players have already taken turns. If a new match is returned, the user must
take the first turn. Your game is responsible for handling turn-taking
regardless of whether a new or existing match is loaded.

Selecting players with the default user interface

Play Games Services provides a default player selection UI that lets players
select their friends to invite to a match or select to be auto-matched with
random players. To start a match from the default player selection UI, call
ShowPlayerSelectUI(). If the call
is successful, the game displays a default player selection UI that prompts the user
to select match invitees and the number of
players for auto-matching. The user's player selection criteria is returned via the provided
PlayerSelectUICallback.

If you want to create a match without using the default player selection UI,
your game must provide the invitee player IDs and auto-match criteria in the
TurnBasedMatchConfig object that
you pass to CreateTurnBasedMatch().

Optionally, you might want to ensure that only players who are interested in a
specific type of game variant are auto-matched together. If there are
different versions of your app, your game can also use variants to ensure that only
players who are on compatible versions are auto-matched. To specify a variant
when creating a turn-based match, use the SetVariant()
method. Your game can also use
SetExclusiveBitMask() to pair
auto-matched players who are interested in playing specific exclusive roles in a game.

Taking the first turn

If the CreateTurnBasedMatch() call
is successful, Play Games services returns a
TurnBasedMatch via the provided
TurnBasedMatchCallback.
Before proceeding, remember to initialize the game data as needed by your game.
For example, you might need to initialize the starting positions for players in
a strategy game or initialize the first hand for players in a card game.

If the call returns a false value, this indicates that the game data is
uninitialized because no player has taken a turn yet (that is, the current
player is the first player in this match). Your game can initialize the game data and
store it in a byte array. The size of the game data must be 128 KB or less.

If the call returns a true value, this indicates that the game has
already started and the game data is already initialized, so make sure your
game does not reinitialize the data.

Optionally, call TakeMyTurn() now.
If your initial state is based on a
random value (for example, a card game where the player starts with a random hand)
and your game does not call TakeMyTurn()
to persist the
data to Google's servers, the player could keep restarting the first turn to
try to get a better starting position.

Let the player perform game actions, and if appropriate, update the byte
array containing the game data.

Save the game data to Google's servers by calling
TakeMyTurn(). Your game can specify
the next player's participant ID, or specify AUTOMATCHING_PARTICIPANT to let Play Games services
find a player for auto-matching. Your game can let match participants take turns even
when not all invited players have joined or when there are auto-match slots
still available. To get players into gameplay faster, your game should let players
take their turn as soon as they join. When you call
TakeMyTurn(), Play Games services
sends a notification to the pending participant and updates the turn
data on all participants' devices asynchronously.

When the next player takes a turn, make sure to load the initialized data
by calling Data()
before you let the player perform game actions.

The following snippet shows how you might initialize a match and let the first
player take a turn.

Implementing auto-matching

When your game calls
CreateTurnBasedMatch(), and
requests auto-matching by specifying
MinimumAutomatchingPlayers()
and/or MaximumAutomatchingPlayers(),
Play Games services
first attempts to match the player to an existing game. If a match is found that meets
the player's auto-match criteria, Play Games services automatically joins the
player and any invited players as auto-matched players into the existing match.
If no match is found, your game should signal that it is available for
auto-matching:

Prompt the initiating player to take the first turn.

Optionally, after the initiating player completes their first turn, your game
can also let other invited players who joined the match take their first turns.

To trigger auto-matching, call
TakeMyTurn() and pass in
AUTOMATCHING_PARTICIPANT in the next_participant parameter.

Handling invitations

Once a player has signed in to your game, the player may receive invitations to
join a turn-based match created by another player. To save coding time and
provide users with a consistent UI for responding to match invitations across
applications, you can use the default match inbox UI provided by the SDK. To
launch the default match inbox UI, call
ShowMatchInboxUI().

Note: If an invited participant declines an invitation without taking a
turn, the match is canceled. An auto-matched player can leave without
canceling the match as long as that player has not taken a turn.

To handle invitations for turn-based matches if your game is not using the default match Inbox UI,
you can register a callback via
SetOnMultiplayerInvitationEvent.
The following methods can be used to manipluate a received invitation:

Call this method if the user received a match invitation and wants to
accept the invitation. Calling this method changes
the user's participant status to ParticipantStatus::JOINED. The user can then proceed to take
a turn.

Call this method if the user received a match invitation but
wants to stop the match from proceeding. Calling this method effectively
cancels the match and removes the match from all GameServices
objects registered to
this user. The user's participant status changes to ParticipantStatus::DECLINED, and the
match status changes to MatchStatus::CANCELED. Other participants see this match under the
Completed Matches category in the match list UI.

Call this method if the user received a match invitation and wants
to permanently ignore the invitation. Calling this method
removes the invitation from all GameServices objects
registered to this user. The user's participant status and the match status
stay unchanged. To other participants in the match, the user still appears
to be invited.

Taking a turn

After the first player takes a turn, your game can let the same participant or another
participant take the next turn. Generally, turn-taking involves fetching the
most recent match data from Play Games services, letting the participant
interact with your game, and calling TakeMyTurn() to
update the match data and pass the turn to another participant.

In order for a participant to take a turn, the match must be in the MY_TURN state. Your game
can use the TurnBasedMatch object to
verify this.

Check the match state by calling
Status().
A result of MY_TURN indicates that the local participant can take a turn.

Load the most recent match data from Play Games services by calling
Data()
and render your game accordingly.

Let the user perform game actions and, if appropriate, persist the
updated game data to a byte array.

Determine the pending participant who should take the next turn. This is
usually dependent on the order of play specified by your game design. The
pending participant can be another player in the match or the participant
whose turn it is. Your game can also pass the turn to the next player
joining by auto-match, by setting the pending participant to AUTOMATCHING_PARTICIPANT.

Call TakeMyTurn() to update the
Play Games services with the latest game data and pass the turn
to the pending participant. Play Games services returns the status of
your match update operation via the provided
TurnBasedMatchCallback. If the
update is successful, Play Games services sends a
notification to the pending participant to inform them that it's their turn.

After invoking this method, the user sees this match
under the Their Turn list in the match list UI.

If a participant ID is specified in the method call, that participant becomes
the current player and can play a turn. The first time this happens to an
invited player, the player receives an invitation notification. Subsequently,
the player receives a turn based match notification.

If AUTOMATCHING_PARTICIPANT is specified, a participant will attempt to be found via
auto-matching. You can only use the special auto-matching participant if there are auto-matching
slots available in the current match.

Your game can call TakeMyTurn()
with the current player as the pending
participant. In this case, Play Games services uploads the game data
but no notification is sent.

The following snippet shows how you might implement the current player's turn:

Randomizing the order of play

In some games, the order of play is randomized every round that players can
take turns. To randomize the order of play in your game, you can use the
following approach:

In the first round, poll each each participant (that is, each player who
has joined by invitation or by auto-match) in the match to determine if they
are ready to play.

Once all participants are ready, your game can randomly order their participant
IDs, then call takeTurn() consecutively, passing in the participant ID for the
next player according to the randomized order.

Saving game state

You can use the turn-based multiplayer API to manage your game state if your
game state data fits within 128 KB or less. To save game state with the
turn-based multiplayer API:

Call TakeMyTurn() and pass in your
game state data as the matchData parameter.

If the call is successful, Play Games services notifies other participants
in the match about the update and makes the match data available on all
participant devices.

Warning: Using the Saved Games API together with the turn-based multiplayer API
could cause version conflicts because the cloud save and match data are not
updated synchronously. To avoid these conflicts in your game, pick and use
just one API to save your game state.

Your game should try to save game data for a partially-finished
turn whenever a player's turn is interrupted and the player has to temporarily
leave the game (for example, because of an incoming phone call). To do this,
override your activity's method to call
TakeMyTurn(). Make sure to specify
the current player as
the pending participant by using the same participant ID as in the last call to
TakeMyTurn(). If successful, the call
stores the game data in Google's servers but does not
generate a new turn notification.

Completing a match

When the match has been played to completion (for example, a user has won the
game), your game should call
FinishMatchDuringMyTurn()
to upload the user's game data and signal to the other participants that the
match is over. The match then appears under the
Completed Matches category in the user's match list UI.

Once a player calls
FinishMatchDuringMyTurn() for
the first time in the match, your game cannot call
TakeMyTurn() again in this match.
Play Games services sends a notification to all other
match participants to inform them that the match is over. These participants
see this match under Your Turn category in their respective match list UIs.
At this point, your game can call
ConfirmPendingCompletion()
for these participants to acknowledge the match results. Invoking this method also
moves the match to the Completed Matches category in the participant's match
list UI.

Calling this method changes the match status changes to MatchStatus::COMPLETED.
After FinishMatchDuringMyTurn()
is called for the first time in the match, Play Games services sends a notification to the other
match participants to inform them that the match is over.

Calling this method acknowledges the match results of a match with status
MatchStatus::PENDING_COMPLETION. After
FinishMatchDuringMyTurn().

Leaving a match

Participants can choose to leave at any time during the match, while allowing
the match to continue. To signal that a participant is leaving, your game should call either
LeaveMatchDuringMyTurn() or
LeaveMatchDuringTheirTurn(). When a
participant leaves a match, the match can still continue with other
participants as long as one of the following conditions is met:

There are two or more other remaining participants, or

There is one remaining participant and at least one empty auto-match slot
available.

Otherwise, the match is canceled.

In general, when a participant leaves a match, another player cannot join and
take that participant's place. One exception is when a player who joined by auto-match
and who has not taken a turn calls
LeaveMatchDuringMyTurn(). In this
case, the match attempts to find another player who can take over the place of the participant
who left.

Removes the match from all GameServices objects registered
to this user. You
should only invoke this method when it is MatchStatus::THEIR_TURN. Calling this method changes
the user's participant status to ParticipantStatus::LEFT. If only one more participant
remains, the match status changes to MatchStatus::Canceled.

Removes the match from all GameServices objects registered to the user. You
should only invoke this method when match status is MatchStatus::MY_TURN
Calling this method changes the user's participant status to
ParticipantStatus::LEFT.

If only one more participant remains, the match status changes to
MatchStatus::CANCELED.

If a participant is specified in the method call, that participant becomes
the current player and can play a turn. The first time this happens to an
invited player, the player receives an invitation notification. Subsequently,
the player receives a turn notification.

If auto-matching slots are available, the AUTOMATCHING_PARTICIPANT can also be specified for
the next participant.

Canceling a match

Your game can end a match for all participants before the match is played to normal
completion, by calling CancelMatch().
After calling this method, your game cannot call
TakeMyTurn()
again in this match; the match now appears under the Completed Matches
category in the match list UI.

Removes the match from all GameServices objects
registered to the user. You
should only invoke this method on the user's turn in an active match.
Calling this method changes the user's participant status to
ParticipantStatus::LEFT and the match status changes to MatchStatus::CANCELED.

Dismissing a match

Your game can let users dismiss a turn or invitation so that they do not have to see
the match again. This hides the match from the dismisser's match list UI and
causes gameplay to stall on the dismisser's turn; the match ends when canceled, or on expiration
after two weeks.
To other participants, the dismisser still appears as a participant in the match. Another
player cannot take the dismisser's place.

Removes the match from all GameServices objects
registered to the user. The user's participant status is not changed.

Tracking match expiration

A match can expire if a player does not respond to a match or turn notification
for two weeks (for example, after a player whose turn it is selects Dismiss
in the default match list UI). You can use the following approach on the game
client to identify which player caused a game to expire:

Load a list of the currently signed-in player's list of games by calling
FetchMatches().

Filter that list for matches in the MatchStatus::EXPIRED state.

If a match participant has ParticipantStatus::UNRESPONSIVE state, it indicates that this
player has let the game expire.

Implementing a rematch

When a match is over, a participant may want to play a rematch with the same
set of invited and auto-match opponents. Your game can initiate a rematch by
invoking Rematch().
Your game can only invoke this method when the match state is
MatchStatus::COMPLETE, and no other participants have requested a rematch. If the call is
successful,
Play Games services sends invitation notifications to all rematched opponents.

Creates a new turn-based match object with the same participants as the
previous match. The user must then take a first turn. If another participant already
requested a rematch,
calling this method returns a MultiplayerStatus::ERROR_MATCH_ALREADY_REMATCHED error.

If your game uses the default match inbox UI, players can also initiate rematches
from that UI.