Backfill
Backfill is a flow that allows players to join a game that has already started.
Backfill can have different goals:
- To start a match faster, without all the required players. In this case, backfill is initiated by the Matchmaker when the Matchmaker configuration has the
backfill
property set totrue
. - To keep a steady number of players in a match even if players are leaving. In this case, the game server initiates the backfill when creating a backfill ticket.
Even if a configuration has the property backfill
set to false
, backfill will still work when a backfill ticket is created.
Backfill flow
The following diagram shows the backfill flow
- When the server is allocated, it fetches the allocation payload information and the Matchmaking Results. The Matchmaking results contain the backfill ticket ID that was created by the matchmaker as well as important information needed to create backfill tickets.
- The server fetches a Multiplay Hosting token is used to authenticate the Game Server to the Matchmaker service.
- The Game Server approves the backfill ticket every second. This is required to prove to the Matchmaker service that the Game Server is still running.
- When a new ticket comes in, if it is compatible, the Matchmaker service will add it to an existing backfill ticket.
- Once the ticket is added to a backfill match, the next time the Game Server approves the backfill ticket, the player ticket will be assigned to the server.
- Once the match is full, the Game Server deletes the backfill ticket.
A Game Server is responsible for keeping a backfill ticket up-to-date. For example, if a player leaves or joins the server outside of Matchmaker, the Game Server needs to inform the Matchmaker service by updating the backfill ticket.
When a game server needs to backfill players who have left the game and there aren't any backfill tickets, the Game Server creates a new backfill ticket.
If a backfill ticket is not approved regularly by the Game Server, then the Matchmaker service automatically deletes the ticket. This prevents backfill tickets from Game Servers that are not running from holding player tickets for no reason.
If a backfill ticket is deleted, either timed out by the Matchmaker service or by the game server, the tickets that were not assigned are put back into the pool of tickets.
Create a backfill ticket
The following code sample demonstrates how to create a backfill ticket from a Game Server:
Unity SDK
// Set the Match Properties. These properties can also be found in the Allocation Payload (cf Allocation Payload)
var teams = new List<Team>{
new Team( "Red", "9c8e302e-9cf3-4ad6-a005-b2604e6851e3", new List<string>{ "c9e6857b-a810-488f-bacc-08d18d253b0a" } ),
new Team( "Blue", "e2d8f4fd-5db8-4153-bca7-72dfc9b2ac09", new List<string>{ "fe1a52cd-535a-4e34-bd24-d6db489eaa19" } ),
};
// Define the Players of the match with their data.
var players = new List<Unity.Services.Matchmaker.Models.Player>
{
new (
"c9e6857b-a810-488f-bacc-08d18d253b0a",
new Dictionary<string, object>
{
{ "Team", "Red" }
}),
new (
"fe1a52cd-535a-4e34-bd24-d6db489eaa19",
new Dictionary<string, object>
{
{ "Team", "Blue" }
})
};
var matchProperties = new MatchProperties(teams, players);
var backfillTicketProperties = new BackfillTicketProperties(matchProperties);
// Set options for matchmaking
var options = new CreateBackfillTicketOptions("queue", "127.0.0.1:8080", new Dictionary<string, object>(), backfillTicketProperties);
// Create backfill ticket
string ticketId = await MatchmakerService.Instance.CreateBackfillTicketAsync
(options);
// Print the created ticket id
Debug.Log(ticketId);
CURL
# Fetch a Multiplay token
curl --location --request POST ‘http://localhost:8086/token
# Transform match properties in a base64 format
matchProperties=$(echo '{
"matchProperties": {
"teams": [
{
"teamName": "Red Team",
"teamId": "14f18a3e-921d-4165-90b6-ada353e186ca",
"playerIDs": [
"c9e6857b-a810-488f-bacc-08d18d253b0a"
]
},
{
"teamName": "Blue Team",
"teamId": "5aa8ae3b-d5b6-463a-9795-9bc10210dc86",
"playerIDs": [
"fe1a52cd-535a-4e34-bd24-d6db489eaa19"
]
}
],
"players": [
{
"id": "c9e6857b-a810-488f-bacc-08d18d253b0a",
"customData": {
"Team": "Red"
}
},
{
"id": "fe1a52cd-535a-4e34-bd24-d6db489eaa19",
"customData": {
"Team": "Blue"
}
}
],
"region": "05083faf-3795-47b8-a0dc-c626089c5ac9",
"backfillTicketId": "dc156067-d140-4c5e-b7d4-90ec51c8333f"
}
}' | base64)
# Send create backfill ticket request
curl --location --request POST 'https://matchmaker.services.api.unity.com/v2/backfill' \
--header 'Authorization: Bearer <MULTIPLAY TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
"poolId": "e642781a-558f-4c56-a135-c655331cdeee”, # Information retrieved from the allocation payload
"connection": "127.0.0.1:8081",
"properties": {
"data": "'+$matchProperties+'"
}
}'
Approve a backfill ticket
When approving a backfill ticket, the game server informs the Matchmaker that the game server is still running and expecting new tickets from the Matchmaker. Unity suggests approving a backfill ticket every second. If there isn’t a call to approve the backfill ticket after a while, the Matchmaker service automatically deletes the ticket.
The following code sample demonstrates how to approve a backfill ticket:
Unity SDK
// Approve a backfill ticket
// The backfill ticket retrieved as a response can then be updated to be used in the Update API
var backfillTicket = await MatchmakerService.Instance.ApproveBackfillTicketAsync("<backfill ticket id here>");
CURL
curl --location --request POST 'https://matchmaker.services.api.unity.com/v2/backfill/{BackfillTicketId}/approvals' \
--header 'Authorization: Bearer <MULTIPLAY TOKEN>' \
--header 'Content-Type: application/json'
Update a backfill ticket
Backfill tickets should be updated when a new player joins the match from outside Matchmaker, or when a player leaves the match. Updating backfill tickets enables the game server to inform Matchmaker that the match composition has changed.
The following code sample demonstrates how to update a pre-existing backfill ticket:
// Retrieve the backfill information from the approve backfill call
var backfillTicket = await MatchmakerService.Instance.ApproveBackfillTicketAsync("1459800b-d463-4197-a903-f00041fdbf6f");
// Add a new player to the backfill ticket
var newPlayer = new Player(
"6ebbc1f9-1c42-479c-b80d-9b6f6aa281f3",
new Dictionary<string, object>
{
{ "Team", "Red" }
});
backfillTicket.Properties.MatchProperties.Players.Add(newPlayer);
backfillTicket.Properties.MatchProperties.Teams[0].PlayerIds.Add(newPlayer.Id);
// remove a player from the backfill ticket
var playerIdToRemove = "fe1a52cd-535a-4e34-bd24-d6db489eaa19";
var playerToRemove = backfillTicket.Properties.MatchProperties.Players.FirstOrDefault(p => p.Id.Equals(playerIdToRemove));
backfillTicket.Properties.MatchProperties.Players.Remove(playerToRemove);
backfillTicket.Properties.MatchProperties.Teams[0].PlayerIds.Remove(playerIdToRemove);
await MatchmakerService.Instance.UpdateBackfillTicketAsync(backfillTicket.Id, backfillTicket);
CURL
# Fetch a Multiplay token
curl --location --request POST ‘http://localhost:8086/token
# Transform match properties in a base64 format
matchProperties=$(echo '{
"matchProperties": {
"teams": [
{
"teamName": "Red Team",
"teamId": "14f18a3e-921d-4165-90b6-ada353e186ca",
"playerIDs": [
"6ebbc1f9-1c42-479c-b80d-9b6f6aa281f3",
]
},
{
"teamName": "Blue Team",
"teamId": "5aa8ae3b-d5b6-463a-9795-9bc10210dc86",
"playerIDs": [
"fe1a52cd-535a-4e34-bd24-d6db489eaa19"
]
}
],
"players": [
{
"id": "6ebbc1f9-1c42-479c-b80d-9b6f6aa281f3",
"customData": {
"Team": "Red"
}
},
{
"id": "fe1a52cd-535a-4e34-bd24-d6db489eaa19",
"customData": {
"Team": "Blue"
}
}
],
"region": "05083faf-3795-47b8-a0dc-c626089c5ac9",
"backfillTicketId": "dc156067-d140-4c5e-b7d4-90ec51c8333f"
}
}' | base64)
# Send update backfill ticket request
curl --location --request PUT 'https://matchmaker.services.api.unity.com/v2/backfill/{BackfillTicketId}' \
--header 'Authorization: Bearer <MULTIPLAY TOKEN>' \
--header 'Content-Type: application/json' \
--data-raw '{
"poolId": "e642781a-558f-4c56-a135-c655331cdeee”, # Information retrieved from the allocation payload
"connection": "127.0.0.1:8081",
"properties": {
"data": "'+$matchProperties+'"
}
}'
When a backfill ticket is updated by the Game Server, all unassigned tickets are released into the pool of tickets.
Delete a backfill ticket
A backfill ticket should be deleted when:
- The server doesn’t require new tickets.
- The server is stopping.
The following code sample demonstrates how to delete a backfill ticket:
Unity SDK
await MatchmakerService.Instance.DeleteBackfillTicketAsync
("1459800b-d463-4197-a903-f00041fdbf6f");
CURL
curl --location --request DELETE 'https://matchmaker.services.api.unity.com/v2/backfill/{BackfillTicketId}' \
--header 'Authorization: Bearer <MULTIPLAY TOKEN>' \
--header 'Content-Type: application/json'