バックフィル

Backfill (バックフィル) は、すでに開始されているゲームにプレイヤーが参加できるようにするフローです。

バックフィルには、以下のようなさまざまな目的があります。

  • 必要なプレイヤー数がすべて揃わなくても、早くマッチを開始する。この場合、Matchmaker の設定で backfill プロパティが true に設定されていると、Matchmaker によってバックフィルが開始されます。
  • プレイヤーが離脱しても、マッチ内で安定したプレイヤー数を維持する。この場合、バックフィルチケットの作成時にゲームサーバーがバックフィルを開始します。

設定で backfill プロパティが false に設定されていても、バックフィルチケットが作成されるとバックフィルは機能します。

バックフィルのフロー

以下の図は、バックフィルのフローを示しています

バックフィルのフロー

  1. サーバーが割り当てられると、サーバーは割り当てペイロードの情報と マッチメイキングの結果 を取得します。マッチメイキングの結果には、Matchmaker によって作成されたバックフィルチケット ID と、バックフィルチケットの作成に必要な重要な情報が含まれています。
  2. サーバーは、Matchmaker サービスに対してゲームサーバーの認証を行うための Multiplay Hosting トークンを取得します。
  3. ゲームサーバーはバックフィルチケットを毎秒承認します。これは、ゲームサーバーがまだ実行中であることを Matchmaker サービスに示すために必要です。
  4. 新しいチケットが入ってきて、適合するチケットである場合、Matchmaker サービスはそれを既存のバックフィルチケットに追加します。
  5. チケットがバックフィルマッチに追加されると、次にゲームサーバーがバックフィルチケットを承認するときに、そのプレイヤーのチケットがサーバーに割り当てられます。
  6. マッチが満員になると、ゲームサーバーはバックフィルチケットを削除します。

ゲームサーバーは、バックフィルチケットを最新の状態に保つ責任があります。例えば、プレイヤーが Matchmaker の外側でサーバーから離脱したりサーバーに参加する場合、ゲームサーバーはバックフィルチケットを更新することで Matchmaker サービスに通知する必要があります。

ゲームサーバーがゲームから離脱したプレイヤーをバックフィルする必要があり、バックフィルチケットがない場合、ゲームサーバーは新しいバックフィルチケットを作成します。

バックフィルチケットがゲームサーバーによって定期的に承認されない場合、Matchmaker サービスはそのチケットを自動的に削除します。これにより、実行中でないゲームサーバーのバックフィルチケットによって理由もなくプレイヤーチケットが保持されるのを防ぎます。

バックフィルチケットがタイムアウトになって Matchmaker サービスによって削除されるか、またはゲームサーバーによって削除された場合、割り当てられなかったチケットはチケットのプールに戻されます。

バックフィルチケットの作成

以下のコードサンプルは、ゲームサーバーからのバックフィルチケットの作成方法を示しています。

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+'"
  }
}'

バックフィルチケットの承認

バックフィルチケットを承認する際、ゲームサーバーは Matchmaker に、ゲームサーバーがまだ実行中であり、Matchmaker からの新しいチケットを待っていることを通知します。Unity では、バックフィルチケットを毎秒承認することを推奨しています。しばらくしてもバックフィルチケットを承認するための呼び出しがない場合、Matchmaker サービスは自動的にそのチケットを削除します。

以下のコードサンプルは、バックフィルチケットの承認方法を示しています。

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'

バックフィルチケットの更新

新しいプレイヤーが Matchmaker の外側からマッチに参加するときや、プレイヤーがマッチから離脱するときは、バックフィルチケットを更新する必要があります。バックフィルチケットを更新することで、ゲームサーバーはマッチの構成が変更されたことを Matchmaker に通知できます。

以下のコードサンプルは、既存のバックフィルチケットの更新方法を示しています。

// 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+'"
  }
}'

バックフィルチケットがゲームサーバーによって更新されると、割り当てられていないすべてのチケットがチケットのプールにリリースされます。

バックフィルチケットの削除

以下の場合に、バックフィルチケットを削除する必要があります。

  • サーバーが新しいチケットを必要としていない。
  • サーバーが停止中である。

以下のコードサンプルは、バックフィルチケットの削除方法を示しています。

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'