クイック スタート: GDK
Microsoft Game Development Kit (GDK) の PlayFab Services SDK の使用を開始します。 次の手順に従ってプロジェクトにライブラリを含め、基本的な PlayFab 機能のサンプル コードを試します。
このクイックスタートでは、GDK を使用して最初の PlayFab API 呼び出しを行います。 続行する前に、「クイック スタート: ゲーム マネージャー」の手順を完了していることを確認してください。これにより、PlayFab アカウントがあり、PlayFab ゲーム マネージャーに精通していることを確認します。
要件
- PlayFab 開発者アカウント。
-
Visual Studio 2019 または 2022 がインストールされている。
- GDK 開発の Visual Studio 要件の詳細については、「SDK およびツールの要件」を参照してください。
プロジェクトのセットアップ
他の GDK 拡張機能ライブラリと同様に、プロジェクト プロパティを使用して PlayFab Services SDK を追加します。 プロジェクトの構成プロパティ]で、[ゲーム デスクトップ]>[全般] の下で、[ゲーム拡張機能ライブラリ] を選択します。 プロンプトで、[PlayFab.Services.C] にチェックを付けます。
Init とログイン
ヘッダー
含まれるすべての PlayFab 機能にアクセスするには、PFServices.h を含めます。
#include <playfab/services/PFServices.h>
初期化
PlayFab の初期化には、PFServicesInitialize と PFServiceConfigCreateHandle の 2 つの関数呼び出しが必要です。 この初期化の結果は、PFServiceConfigHandle です。 このハンドルを後続のログイン呼び出しに指定し、呼び出しを PlayFab バックエンドの正しいタイトルに転送します。
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 の取得と管理の詳細については、「ユーザー ID と XUser」を参照してください。
ログイン呼び出しを行った後、XAsyncGetStatus を使用して呼び出しの状態をチェックできます。 状態は E_PENDING として開始され、呼び出しが正常に完了した後に S_OK に変更されます。 何らかの理由で呼び出しが失敗した場合、その失敗が状態に反映されます。 すべての PlayFab Services 呼び出しでのエラー処理は、このように行われます。
S_OK の結果と共に、PFEntityHandle が返されます。 このハンドルを使用して、ログインしたプレイヤーとして以降の PlayFab 呼び出しを行います。 これには、PlayFab サービスをそのプレイヤーとして認証するために必要なデータが含まれています。
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);
サービス呼び出し
プレイヤーをログインした後、PlayFab バックエンドを呼び出すことができるようになります。 現在のプレーヤーの PlayFab にファイルを格納するための呼び出しの例を次に示します。
EntityKey の取得
PlayFab の一部の呼び出しに役立つことの 1 つは、プレーヤーの PFEntityKey を把握することです。 PFEntityToken を取得したら、PFEntityGetEntityKey を使用して PFEntityKey を取得できます。
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 関数を呼び出して新しく作成したコンテナーを埋める、という同様のパターンに従います。
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 を呼び出してください。
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 に実装されている非同期プログラミング モデルに従います。 このプログラミング モデルには、XAsync ライブラリによって提供されるタスクとタスク キューの使用が含まれます。 このモデルには、他の GDK 関数や拡張機能 (Xbox Services API など) との一貫性があります。 複雑さが生じる一方で、非同期操作を高度に制御することもできるようになります。
この例は、PFDataGetFilesAsync を非同期で呼び出す方法を示します。
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 のいずれかを呼び出すときに HTTP_E_STATUS_NOT_FOUND などのエラー HRESULT としてマニフェストされます。
サービスによって返される詳細なエラー メッセージを確認するには、デバッグに関する次のセクションを参照してください。 これらの詳細なエラー メッセージは、開発中に、PlayFab サービスがクライアントからの要求にどのように反応するかを理解するのに役立ちます。
デバッグ
結果を確認し、PlayFab Services SDK の呼び出しをデバッグする最も簡単な方法は、デバッグ トレースを有効にすることです。 デバッグ トレースを有効にすると、デバッガーの出力ウィンドウに結果を表示し、結果をゲーム独自のログにフックすることが両方可能になります。