> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Matchmaking SDK 快速入門

> PlayFab Multiplayer SDK 配對用戶端流程的快速入門逐步解說：初始化程式庫、提交票證，以及接收比賽結果。

本快速入門指南會逐步引導您完成使用 PlayFab Multiplayer SDK 將配對功能新增至遊戲的整個程序。

本教學課程說明如何將票證提交至特定佇列以尋找遊戲。佇列可能對應到一種或多種遊戲模式 (例如：同一個佇列中的搶旗模式和山丘之王模式)。

配對服務負責在佇列中的票證之間尋找比賽。找到比賽時，您的遊戲必須負責將玩家連線在一起進行遊戲。

<Note>
  PlayFab Multiplayer SDK 也提供 PlayFab 大廳的 API。\* 如需 C++ API 的詳細資訊，請參閱 [Lobby SDK 快速入門](/zh-TW/services/playfab/multiplayer/lobby/lobby-getting-started) \* 如需 Unity API 的詳細資訊，請參閱 [Unity 快速入門](/zh-TW/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started) \* 如需 Unreal API 的詳細資訊，請參閱 [Unreal 快速入門](/zh-TW/services/playfab/multiplayer/networking/party-unreal-engine-oss-quickstart)
</Note>

## 先決條件

您需要 [PlayFab 帳戶](https://developer.playfab.com)才能使用 PlayFab Matchmaking。如需建立帳戶的指示，請參閱[快速入門：Game Manager](/zh-TW/services/playfab/live-service-management/gamemanager/quickstart).

## 在 Game Manager 中設定配對佇列

程式庫會將為 Game Manager 中所設定之佇列建立票證的使用者配對在一起。如需如何設定佇列的詳細資料，請參閱[設定配對佇列](/zh-TW/services/playfab/multiplayer/matchmaking/config-queues).

## 下載並設定 PlayFab Multiplayer SDK

下載適用於您平台的 [C/C++ SDK](/zh-TW/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks)，並將提供的標頭和程式庫檔案整合到您的組建中。

<Note>
  本快速入門著重於使用 C/C++ SDK。如需 Unity 和 Unreal 介面，請參閱下列文章：\* [Unity 快速入門](/zh-TW/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/multiplayer-unity-sdk-getting-started) \* [Unreal 快速入門](/zh-TW/services/playfab/multiplayer/networking/party-unreal-engine-oss-quickstart)
</Note>

## 登入 PlayFab 實體

若要使用 PlayFab Lobby SDK，您需要使用 PlayFab 實體索引鍵和實體權杖來驗證用戶端。透過 [LoginWithCustomId](https://learn.microsoft.com/en-us/rest/api/playfab/client/authentication/login-with-custom-id) REST API 登入，以取得 PlayFab 實體索引鍵和權杖組。此 API 也可透過 [PlayFab REST SDK](/zh-TW/services/playfab/sdks/playfab-sdk-intro) 以 C/C++ 投影的形式使用。

<Note>
  LoginWithCustomId 是開始使用 PlayFab 功能的快速方式，但並非用來作為您正式推出時的登入機制。如需登入指引，請參閱[登入基本概念和最佳做法](/zh-TW/services/playfab/identity/player-identity/login/login-basics-best-practices).
</Note>

## 初始化 PlayFab Multiplayer SDK

依照下列基本步驟初始化 PlayFab Multiplayer SDK：

1. 呼叫 [PFMultiplayerInitialize](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayerinitialize) 以初始化 SDK
2. 呼叫 [PFMultiplayerSetEntityToken](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayersetentitytoken)，設定程式庫代表玩家使用的實體索引鍵和權杖。

```cpp theme={null}
static PFMultiplayerHandle g_pfmHandle = nullptr;
...
...
HRESULT hr = S_OK;

// Initialize the PFMultiplayer library.
hr = PFMultiplayerInitialize(titleId, &g_pfmHandle);
if (FAILED(hr))
{
    // handle initialize failure
}

// Set an entity token for a local user. The token is used to authenticate PlayFab operations on behalf of this user. 
// Tokens can expire, and this API token should be called again when this token is refreshed.
hr = PFMultiplayerSetEntityToken(g_pfmHandle, localUserEntity, entityToken);
if (FAILED(hr))
{
    // handle set entity token failure
}
```

## 建立配對票證

您可以使用 [PFMultiplayerCreateMatchmakingTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayercreatematchmakingticket) 建立配對票證，並在其中指定應參與比賽的所有本機使用者，以及要與這些使用者相關聯的任何屬性。

此函式也接受 [PFMatchmakingTicketConfiguration](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingticketconfiguration)，您可以在其中指定票證所屬的佇列、票證的逾時，以及您想要配對到此票證中的任何遠端使用者。

### 單一本機使用者的配對

您可以呼叫 **PFMultiplayerCreateMatchmakingTicket**，為單一本機使用者開始配對。

```cpp theme={null}
const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = yourQueueName;

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"tank\"}\"";

const PFMatchmakingTicket* ticket;
HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
    g_pfmHandle,
    1, // number of local users
    localUserEntity,
    &attributes,
    &configuration,
    nullptr, // optional asyncContext
    &ticket);
RETURN_IF_FAILED(hr);
```

### 與一群遠端使用者進行配對

若要開始與遠端使用者進行群組配對，將其中一個用戶端視為領導者會很有幫助。讓領導者使用 **PFMultiplayerCreateMatchmakingTicket** 建立票證，並透過 **configuration** 參數指定群組中的其他使用者。建立票證後，呼叫 **GetTicketId** 以取得票證識別碼。透過外部機制 (例如網路網格或共用的 PlayFab 大廳) 將此識別碼傳送給其他每位使用者，並讓每個用戶端以票證識別碼呼叫 **PFMultiplayerJoinMatchmakingTicketFromId** 來加入配對票證。等候指定的玩家加入時，票證狀態會是 **PFMatchmakingTicketStatus::WaitingForPlayers**，所有玩家都加入票證後，狀態會變更為 **PFMatchmakingTicketStatus::WaitingForMatch**。

```cpp theme={null}
// Creating the ticket on the leader's client

const char* remoteMemberEntityId1 = ...;
const char* remoteMemberEntityId2 = ...;

std::vector<PFEntityKey> remoteMatchMemberEntityKeys;
remoteMatchMemberEntityKeys.push_back({ remoteMemberEntityId1, "title_player_account" });
remoteMatchMemberEntityKeys.push_back({ remoteMemberEntityId2, "title_player_account" });

const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = yourQueueName;
configuration.membersToMatchWithCount = 2; // number of remote members to match with
configuration.membersToMatchWith = remoteMatchMemberEntityKeys.data();

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"tank\"}\"";

const PFMatchmakingTicket* ticket;
HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
    g_pfmHandle,
    1, // number of local users
    localUserEntity,
    &attributes,
    &configuration,
    nullptr, // optional asyncContext
    &ticket);
RETURN_IF_FAILED(hr);

// Getting the ticket ID

PCSTR ticketId;
hr = PFMatchmakingTicketGetTicketId(ticket, &ticketId);
RETURN_IF_FAILED(hr);
```

```cpp theme={null}
// Joining the ticket on the other players' clients

const char* attributes = "\"{\"color\":\"blue\", \"role\":\"healer\"}\"";
const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

const PFMatchmakingTicket* ticket;
HRESULT hr = PFMultiplayerJoinMatchmakingTicketFromId(
    g_pfmHandle,
    1, // number of local users
    localUserEntity,
    &attributes,
    ticketId,
    yourQueueName,
    nullptr, // optional asyncContext
    &ticket);
```

### 多個本機使用者的配對

與多個本機使用者進行配對時，您需要傳入索引鍵清單，而不是將單一 **PFEntityKey** 傳入 **PFMultiplayerCreateMatchmakingTicket** 或 **PFMultiplayerJoinMatchmakingTicketFromId** 函式。同樣地，您需要為每位使用者傳入屬性清單。每個清單項目的位置都應彼此對應。也就是說，屬性清單中的第一個項目應該是 **PFEntityKey** 清單中第一位玩家的屬性。

```cpp theme={null}
const char* yourQueueName = ...; // This is the name of the queue you configured in Game Manager.

PFMatchmakingTicketConfiguration configuration{};
configuration.timeoutInSeconds = 120;
configuration.queueName = queueName;

std::vector<PFEntityKey> localMatchMemberEntityKeys{ ... };
std::vector<PCSTR> localMatchMemberAttributes{ ... };

const PFMatchmakingTicket* ticket;
HRESULT hr = PFMultiplayerCreateMatchmakingTicket(
    g_pfmHandle,
    static_cast<uint32_t>(localMatchMemberEntityKeys.size())
    localMatchMemberEntityKeys.data(),
    localMatchMemberAttributes.data(),
    &configuration,
    nullptr, // optional asyncContext
    &ticket);
RETURN_IF_FAILED(hr);
```

## 檢查配對票證的狀態

您必須呼叫 [PFMultiplayerStartProcessingMatchmakingStateChanges](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges) 來接收狀態變更，以檢查票證的更新，並在處理完這些狀態變更後呼叫 [PFMultiplayerFinishProcessingMatchmakingStateChanges](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerfinishprocessingmatchmakingstatechanges)。

每當票證狀態變更時，SDK 都會傳回 **TicketStatusChanged** 狀態變更；配對完成時，則會傳回 **TicketCompleted** 狀態變更。

### 使用 Matchmaking 用戶端 SDK 的範例

```cpp theme={null}
HRESULT hrTicketError = S_OK;

uint32_t stateChangeCount;
const PFMatchmakingStateChange * const * stateChanges;
hr = PFMultiplayerStartProcessingMatchmakingStateChanges(g_pfmHandle, &stateChangeCount, &stateChanges);
RETURN_IF_FAILED(hr);

for (uint32_t i = 0; i < stateChangeCount; ++i)
{
    const PFMatchmakingStateChange& stateChange = *stateChanges[i];

    switch (stateChange.stateChangeType)
    {
        case PFMatchmakingStateChangeType::TicketStatusChanged:
        {
            const auto& ticketStatusChanged = static_cast<const PFMatchmakingTicketStatusChangedStateChange&>(stateChange);

            PFMatchmakingTicketStatus status;
            if (SUCCEEDED(PFMatchmakingTicketGetStatus(ticketStatusChanged.ticket, &status)))
            {
                printf("Ticket status is now: %i.\n", status);
            }

            break;
        }
        case PFMatchmakingStateChangeType::TicketCompleted:
        {
            const auto& ticketCompleted = static_cast<const PFMatchmakingTicketCompletedStateChange&>(stateChange);

            printf("PFMatchmaking completed with Result 0x%08x.\n", ticketCompleted.result);

            if (FAILED(ticketCompleted.result))
            {
                // On failure, we must record the HRESULT so we can return the state change(s) and then bail
                // out of this function.
                hrTicketError = ticketCompleted.result;
            }

            break;
        }
    }
}

hr = PFMultiplayerFinishProcessingMatchmakingStateChanges(g_pfmHandle, stateChangeCount, stateChanges);
RETURN_IF_FAILED(hr);

// Now that we've returned the state change(s), bail out if we detected ticket failure.
RETURN_IF_FAILED(hrTicketError);
```

## 取得比賽

收到 **PFMatchmakingStateChangeType::TicketCompleted** 狀態變更之後，呼叫 [PFMatchmakingTicketGetMatch](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketgetmatch) 以取得比賽的詳細資料。這些詳細資料會包含比賽識別碼、已配對在一起的使用者、比賽的偏好區域，以及與比賽相關聯之大廳的安排字串。

從 **PFMatchmakingMatchDetails** 結構中擷取所需的任何資訊之後，應使用 [PFMultiplayerDestroyMatchmakingTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket) 終結票證。

### 使用 Matchmaking 用戶端 SDK 的範例

```cpp theme={null}
const PFMatchmakingMatchDetails* match;
HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
RETURN_IF_FAILED(hr);

std::string matchId = match->matchId;
std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);
```

## 取消配對票證

如果您的用戶端基於某些原因想要在 `PFMatchmakingTicketConfiguration` 中設定的逾時之前取消配對程序，請使用票證控制代碼呼叫 [PFMatchmakingTicketCancel](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmatchmakingticketcancel)。

呼叫此 API 不保證票證會被取消。票證仍可能在取消作業處理之前完成，或取消要求可能因網路或服務錯誤而失敗。如果您想要在繼續之前確認票證取消已完成，仍可處理配對狀態變更以取得票證的結果。否則，您可以立即呼叫 [PFMultiplayerDestroyMatchmakingTicket](/zh-TW/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerdestroymatchmakingticket)。

### 使用 Matchmaking 用戶端 SDK 的範例

```cpp theme={null}
HRESULT hr = PFMatchmakingTicketCancel(ticket);

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);
```

## (選用) 將玩家連線到同一個大廳

玩家配對成功後，就可以一起加入大廳。已配對票證的 **PFMatchmakingMatchDetails** 包含 **lobbyArrangementString** 欄位，可用來讓使用者加入同一個大廳。

如需 Lobby 和 Matchmaking 如何互動的詳細資訊，請參閱[同時使用大廳和配對](/zh-TW/services/playfab/multiplayer/lobby/lobby-and-matchmaking).

如需 PlayFab 大廳的詳細資訊，請參閱 [PlayFab Lobby 概觀](/zh-TW/services/playfab/multiplayer/lobby).

### 使用 Matchmaking 用戶端 SDK 的範例

```cpp theme={null}
const PFMatchmakingMatchDetails* match;
HREULT hr = PFMatchmakingTicketGetMatch(ticket, &match);
RETURN_IF_FAILED(hr);

std::string matchId = match->matchId;
std::string lobbyArrangementString = match->lobbyArrangementString;

PFMultiplayerDestroyMatchmakingTicket(g_pfmHandle, ticket);

PFLobbyHandle lobby;
RETURN_IF_FAILED_HR(PFMultiplayerJoinArrangedLobby(
    m_pfmHandle,
    &joiningUser,
    lobbyArrangementString,
    &joinConfig,
    nullptr, // optional asyncContext
    &lobby));
```

## 結論

透過本快速入門，您的遊戲現在應該已經有可正常運作的配對流程。此外，您應該考慮下列事項：

* 您的遊戲如何處理群組組成。
* 使用者等候比賽時，您的遊戲要顯示什麼內容。
* 如何處理失敗和重試。

## 另請參閱

* [Lobby SDK](/zh-TW/services/playfab/multiplayer/lobby/lobby-getting-started)


## Related topics

- [Lobby SDK 快速入門](/zh-TW/services/playfab/multiplayer/lobby/lobby-getting-started.md)
- [PlayFab Lobby 和 Matchmaking SDK](/zh-TW/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md)
- [配對快速入門](/zh-TW/services/playfab/multiplayer/matchmaking/quickstart.md)
- [快速入門](/zh-TW/services/playfab/economy-monetization/economy-v2/quickstart.md)
- [Android 快速入門](/zh-TW/services/playfab/sdks/c/quickstart-android.md)
