> ## 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.

# GDK 快速入門

> 將 PlayFab Services C SDK 延伸模組程式庫新增至 Microsoft GDK 遊戲，並從 XBOX 或 Windows GDK 程式碼進行您的第一次 PlayFab API 呼叫。

# 快速入門：GDK

開始使用適用於 Microsoft Game Development Kit (GDK) 的 PlayFab Services SDK。請依照下列步驟將程式庫納入您的專案，並試用基本 PlayFab 功能的範例程式碼。

本快速入門可協助您使用 GDK 進行第一次 PlayFab API 呼叫。在繼續之前，請確定您已完成[快速入門：Game Manager](/zh-TW/services/playfab/live-service-management/gamemanager/quickstart) 中的步驟，以確保您擁有 PlayFab 帳戶並熟悉 PlayFab Game Manager。

## 需求

* [PlayFab 開發人員帳戶](https://developer.playfab.com)。
* 已安裝 [Visual Studio 2019 或 2022](https://visualstudio.microsoft.com/)。
  * 如需 GDK 開發之 Visual Studio 需求的詳細資訊，請參閱 [SDK 與工具需求](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/getstarted/overviews/sdk-and-tools#install-visual-studio)。

## 專案設定

與其他 GDK 延伸模組程式庫類似，請透過專案屬性新增 PlayFab Services SDK。在專案的 \[組態屬性] 中，於 **Gaming Desktop** > **General** 底下選取 **Gaming Extension Libraries**。在提示中勾選 **PlayFab.Services.C**。

<img src="https://mintcdn.com/microsoft-4404708b/N3T1ucKV7zIMBudj/images/playfab/sdks/c/gdk1.png?fit=max&auto=format&n=N3T1ucKV7zIMBudj&q=85&s=7fef311a1c51b1ef7ed3c6b651ca7c67" alt="選取 PlayFab.Services.C 延伸模組程式庫" width="624" height="288" data-path="images/playfab/sdks/c/gdk1.png" />

## 初始化和登入

### 標頭

納入 **PFServices.h** 以存取所有隨附的 PlayFab 功能：

```cpp theme={null}
#include <playfab/services/PFServices.h>
```

### 初始化

PlayFab 初始化需要兩個函式呼叫：**PFServicesInitialize** 和 **PFServiceConfigCreateHandle**。此初始化的結果是一個 **PFServiceConfigHandle**。您會將此控制代碼提供給後續的登入呼叫，以將呼叫導向 PlayFab 後端中正確的遊戲。

```cpp theme={null}
    HRESULT hr = PFServicesInitialize(nullptr); // Add your own error handling when FAILED(hr) == true

    PFServiceConfigHandle serviceConfigHandle{ nullptr };

    hr = PFServiceConfigCreateHandle(
            "https://ABCDEF.playfabapi.com",    // PlayFab API endpoint - obtained in the Game Manager
            "ABCDEF",                           // PlayFab Title id - obtained in the Game Manager
            &serviceConfigHandle);
```

### 登入

取得 **PFServiceConfigHandle** 之後，您就可以使用它進行玩家登入呼叫。在 GDK 中，使用 **PFAuthenticationLoginWithXUserAsync**。此函式可讓您使用 **XUserHandle** 將玩家登入 PlayFab。若要深入了解如何取得和管理 **XUserHandle**，請參閱[使用者身分識別和 XUser](/zh-TW/build/core-features/common/user/player-identity-xuser)。

進行登入呼叫之後，您可以使用 **XAsyncGetStatus** 檢查呼叫的狀態。狀態一開始為 **E\_PENDING**，並在呼叫順利完成後變更為 **S\_OK**。如果呼叫因故失敗，狀態會反映該失敗。所有 PlayFab Services 呼叫的錯誤處理都是以這種方式運作。

除了 **S\_OK** 結果之外，您還會取回 **PFEntityHandle**。您可以使用此控制代碼，以已登入玩家的身分進行後續 PlayFab 呼叫。它包含以該玩家身分向 PlayFab 服務進行驗證所需的任何資料。

```cpp theme={null}
    PFAuthenticationLoginWithXUserRequest request{};
    request.createAccount = true;
    request.user = userHandle; // An XUserHandle obtained from XUserAddAsync

    XAsyncBlock async{};
    HRESULT hr = PFAuthenticationLoginWithXUserAsync(serviceConfigHandle, &request, &async); // Add your own error handling when FAILED(hr) == true
    hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

    std::vector<char> loginResultBuffer;
    PFAuthenticationLoginResult const* loginResult;
    size_t bufferSize;
    hr = PFAuthenticationLoginWithXUserGetResultSize(&async, &bufferSize);
    loginResultBuffer.resize(bufferSize);

    PFEntityHandle entityHandle{ nullptr };
    hr = PFAuthenticationLoginWithXUserGetResult(&async, &entityHandle, loginResultBuffer.size(), loginResultBuffer.data(), &loginResult, nullptr);
```

## 處理暫停與繼續

GDK 遊戲可能會暫停很長一段時間 (例如透過快速繼續)。如果實體權杖在暫停期間到期，SDK 會在繼續時偵測到這種情況並通知您的遊戲。您應該在遊戲生命週期的早期註冊 **TokenExpiredHandler**，以便在需要時重新驗證並重新連線服務。

如需完整詳細資料，請參閱[處理權杖到期](/zh-TW/services/playfab/sdks/c/relogin)。

## 服務呼叫

將玩家登入之後，您現在可以對 PlayFab 後端進行呼叫。以下範例示範如何呼叫以取得目前玩家儲存在 PlayFab 中的檔案。

### 取得 EntityKey

對於某些 PlayFab 呼叫而言，知道玩家的 **PFEntityKey** 會很有用。取得 **PFEntityToken** 之後，您可以使用 **PFEntityGetEntityKey** 擷取 **PFEntityKey**。

```cpp theme={null}
    PFEntityKey const* pEntityKey{};
    std::vector<char> entityKeyBuffer;
    size_t size{};
    HRESULT hr = PFEntityGetEntityKeySize(entityHandle, &size); // Add your own error handling when FAILED(hr) == true

    entityKeyBuffer.resize(size);
    hr = PFEntityGetEntityKey(entityHandle, entityKeyBuffer.size(), entityKeyBuffer.data(), &pEntityKey, nullptr);
```

### 呼叫 GetFiles

所有 PlayFab 呼叫都遵循類似的模式：準備要求物件、進行呼叫 (使用登入取得的 **PFEntityHandle**)、建立接收回應的物件，然後呼叫 **GetResult** 函式來填入新建立的容器。

```cpp theme={null}
    XAsyncBlock async{};
    PFDataGetFilesRequest requestFiles{};
    requestFiles.entity = pEntityKey;

    HRESULT hr = PFDataGetFilesAsync(entityHandle, &requestFiles, &async); // Add your own error handling when FAILED(hr) == true
    hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

    size_t resultSize;
    hr = PFDataGetFilesGetResultSize(&async, &resultSize);

    std::vector<char> getFilesResultBuffer(resultSize);
    PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
    hr = PFDataGetFilesGetResult(&async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
```

## 清除

當您的遊戲準備關閉，或您因其他原因需要清除 PlayFab 時，請確定關閉所有開啟的控制代碼，並呼叫 **PFServicesUninitializeAsync**。

```cpp theme={null}
    PFEntityCloseHandle(entityHandle);
    entityHandle = nullptr;

    PFServiceConfigCloseHandle(serviceConfigHandle);
    serviceConfigHandle = nullptr;

    XAsyncBlock async{};
    HRESULT hr = PFServicesUninitializeAsync(&async); // Add your own error handling when FAILED(hr) == true
    hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage
```

## 非同步 API 模式

適用於 GDK 的 PlayFab Services SDK 遵循 GDK 中實作的[非同步程式設計模型](https://learn.microsoft.com/en-us/gaming/gdk/_content/gc/system/overviews/async-programming-model)。此程式設計模型涉及使用 [XAsync 程式庫](/zh-TW/build/core-features/common/async/async-libraries/async-library-xasync)所提供的工作和工作佇列。此模型與其他 GDK 函式和延伸模組 (例如 XBOX 服務 API) 一致。雖然它確實帶來一些複雜性，但也讓您能高度控制非同步作業。

此範例示範如何對 **PFDataGetFilesAsync** 進行非同步呼叫。

```cpp theme={null}
    auto async = std::make_unique<XAsyncBlock>();
    async->callback = [](XAsyncBlock* async)
    {
        std::unique_ptr<XAsyncBlock> asyncBlockPtr{ async }; // take ownership of XAsyncBlock

        size_t resultSize;
        HRESULT hr = PFDataGetFilesGetResultSize(async, &resultSize);
        if (SUCCEEDED(hr))
        {
            std::vector<char> getFilesResultBuffer(resultSize);
            PFDataGetFilesResponse* getFilesResponseResult{ nullptr };
            PFDataGetFilesGetResult(async, getFilesResultBuffer.size(), getFilesResultBuffer.data(), &getFilesResponseResult, nullptr);
        }
    };

    PFDataGetFilesRequest requestFiles{};
    requestFiles.entity = m_pEntityKey;
    HRESULT hr = PFDataGetFilesAsync(m_entityHandle, &requestFiles, async.get());
    if (SUCCEEDED(hr))
    {
        async.release(); // at this point, the callback will be called so release the unique ptr
    }

```

## 錯誤處理

已完成的 **XAsync** 作業會傳回 HTTP 狀態碼。呼叫 **XAsyncGetStatus()** 或其中一個 **PF\*Get()** API 時，錯誤狀態碼會以失敗 **HRESULT** 的形式呈現，例如 **HTTP\_E\_STATUS\_NOT\_FOUND**。

若要查看服務傳回的詳細錯誤訊息，請參閱下一節的偵錯說明。在開發期間，這些詳細的錯誤訊息有助於您進一步了解 PlayFab 服務如何回應來自用戶端的要求。

## 偵錯

若要查看 PlayFab Services SDK 中任何呼叫的結果並加以偵錯，最簡單的方式是啟用[偵錯追蹤](/zh-TW/services/playfab/sdks/c/tracing)。啟用偵錯追蹤後，您既可以在偵錯工具輸出視窗中查看結果，也可以將結果連結至遊戲本身的記錄。

## 參考

[API 參考文件](/zh-TW/services/playfab/api-references/c/pfauthentication/pfauthentication_members)


## Related topics

- [快速入門](/zh-TW/services/playfab/economy-monetization/economy-v2/quickstart.md)
- [Party 快速入門](/zh-TW/services/playfab/multiplayer/networking/quickstart.md)
- [Android 快速入門](/zh-TW/services/playfab/sdks/c/quickstart-android.md)
- [iOS 快速入門](/zh-TW/services/playfab/sdks/c/quickstart-ios.md)
- [Linux 快速入門](/zh-TW/services/playfab/sdks/c/quickstart-linux.md)
