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

# プレイヤーパブリッシャーデータを使用して複数タイトルのプレイに報酬を付与する

> PlayFab のプレイヤーパブリッシャーデータと CloudScript を使用してクロスタイトルのログインを追跡し、複数のタイトルをプレイするプレイヤーに仮想通貨の報酬を付与します。

報酬は通常、プレイヤーデータ以外の *別の* システムに関連するものですが、この例では簡略化のために仮想通貨の付与を用いて示します。

## 要件

* [PlayFab 開発者アカウント](https://developer.playfab.com)。
* プレイヤーは、同じ資格情報で *両方の* タイトルにサインインする必要があります。1 つのアプローチは、[Login Basics and Best Practices](/services/playfab/identity/player-identity/login/login-basics-best-practices) チュートリアルで説明されている **Recoverable Credentials** を使用することです。匿名アカウントに **Recoverable** ログインを追加する方法については、[Account Linking](/services/playfab/identity/player-identity/login/quickstart) チュートリアルを参照してください。
* この例では [CloudScript](/services/playfab/live-service-management/service-gateway/automation/cloudscript/writing-custom-cloudscript) の実務的な知識が必要です:
  * この例では、プレイヤーのチートを避けるための基本的なデータセキュリティを示します。同様に、タイトルで使用している場合は、カスタムゲームサーバー上でサーバー API を使用することもできます。
* PlayFab を通じてトリガーされる報酬には、適切な PlayFab 機能の使用が必要です。PlayFab の報酬は [**Virtual Currency**](/services/playfab/economy-monetization/economy-v2/tutorials/currencies)、[**Inventory Items**](/services/playfab/player-progression/player-data/player-inventory)、[**Custom Player Data**](/services/playfab/player-progression/player-data/quickstart)、[**Statistics**](/services/playfab/community/leaderboards/tournaments-leaderboards/using-player-statistics) などの形式で提供できます。PlayFab システムの外部で報酬を配布するのは高度なトピックであり、このチュートリアルでは扱いません。

また、CloudScript から実行されるすべてのサーバー API 呼び出しに対して、開発者が適切なエラーハンドリングを使用することを推奨します。

## 各ゲームがログインをパブリッシャーデータに報告する

各ゲームは、ログインが発生したことを報告する必要があります。簡略化のために、この例では、各タイトルにつき、他にプレイされたパブリッシャータイトルごとに *1 つ* の報酬のみを提供します。

カウンターやタイムスタンプ、その他の仕組みを用いてこのアイデアを拡張し、段階的または連続的な報酬を提供することも可能です。

以下の CloudScript は、スタジオの *すべての* ゲームに存在する必要があります。

```javascript theme={null}
// CloudScript/Javascript

var PUBLISHER_USED_TITLES_KEY = "playedTitleIds";
handlers.TrackTitleUsage = function () {
    // Get the User Publisher Data for this player, and convert it into our expected format
    var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY], PlayFabId: currentPlayerId };
    var getResult = server.GetUserPublisherInternalData(getRequest);
    var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is arbitrary, but this example assumes Array<string>
    if (!playedTitlesList)
        playedTitlesList = [];
    // Check if we've played this title already
    var alreadyPlayed = false;
    for (var i = 0; i < playedTitlesList.length; i++)
        alreadyPlayed = alreadyPlayed || playedTitlesList[i] === script.titleId;
    if (alreadyPlayed)
        return; // Nothing to do
    // Update the list of played titles, and re-save
    playedTitlesList.push(script.titleId);
    var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_USED_TITLES_KEY: JSON.stringify(playedTitlesList) } };
    server.UpdateUserPublisherInternalData(setRequest);
}
```

特に、この例では以下の使用を示しています:

* server.[GetUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.getuserpublisherinternaldata)
* server.[UpdateUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.updateuserpublisherinternaldata)。

## 各ゲームが引き換え可能な報酬を確認する

どのタイトルがプレイされたかを追跡した後は、報酬を追跡して付与する必要があります。以下の CloudScript 関数は、他のタイトルをプレイしたかどうかに基づいて、利用可能な報酬を確認し付与します。

```javascript theme={null}
// CloudScript/Javascript

var PUBLISHER_REDEEMED_TITLES_KEY = "redeemedTitleIds";
var MY_CROSS_TITLE_REWARDS = { "AU": 10 };
handlers.CheckCrossTitleRewards = function () {
    // Get the publisher data concerning cross-title rewards for this player
    var getRequest = { Keys: [PUBLISHER_USED_TITLES_KEY, PUBLISHER_REDEEMED_TITLES_KEY], PlayFabId: currentPlayerId };
    var getResult = server.GetUserPublisherInternalData(getRequest);
    var redeemedTitleRewards = JSON.parse(getResult.Data[PUBLISHER_REDEEMED_TITLES_KEY].Value); // format is arbitrary, but this example assumes { [key: string]: Array<string> }
    if (!redeemedTitleRewards)
        redeemedTitleRewards = {};
    var playedTitlesList = JSON.parse(getResult.Data[PUBLISHER_USED_TITLES_KEY].Value); // format is arbitrary, but this example assumes Array<string>
    if (!playedTitlesList)
        playedTitlesList = [];

    // Determine which titles are un-redeemed
    var unredeemedTitleIds = [];
    for (var i = 0; i < playedTitlesList.length; i++) {
        if (!redeemedTitleRewards.hasOwnProperty(playedTitlesList[i]) && playedTitlesList[i] !== script.titleId)
            unredeemedTitleIds.push(playedTitlesList[i]);
    }
    if (unredeemedTitleIds.length === 0)
        return null; // Nothing to redeem

    // Give the cross title rewards
    var multiplier = unredeemedTitleIds.length;
    var actualRewards = {}; // MY_CROSS_TITLE_REWARDS is a global constant, so don't modify it or you'll mess up future calls
    // Please note that the number of API calls that may be made from CloudScript, as well as the total available processing time is limited,
    // and so the number of rewards should be as small as possible (only one VC, in this case)
    for (var eachKey in MY_CROSS_TITLE_REWARDS) {
        actualRewards[eachKey] = MY_CROSS_TITLE_REWARDS[eachKey] * multiplier;
        server.AddUserVirtualCurrency({ PlayFabId: currentPlayerId, VirtualCurrency: eachKey, Amount: MY_CROSS_TITLE_REWARDS[eachKey] }); // Can only add 1 VC at a time
    }

    // Save the Publisher data indicating rewards are claimed
    redeemedTitleRewards[script.titleId] = playedTitlesList;
    var setRequest = { PlayFabId: currentPlayerId, Data: { PUBLISHER_REDEEMED_TITLES_KEY: JSON.stringify(redeemedTitleRewards) } };
    server.UpdateUserPublisherInternalData(setRequest);

    // Tell the client the reward
    return actualRewards;
};
```

<Note>
  この例では、server.[GetUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.getuserpublisherinternaldata) (複数キーのリクエスト)、server.[UpdateUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.updateuserpublisherinternaldata)、および server.[AddUserVirtualCurrency](xref:titleid.playfabapi.com.server.playeritemmanagement.adduservirtualcurrency) の使用を示しています。
</Note>

これらのコードブロックは、以下のステップを表しています:

* PlayFab からデータを取得し、ローカルデータ構造に解析する ([GetUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.getuserpublisherinternaldata) の呼び出し)。
* データを調べ、まだ報酬が付与されていないタイトル ID を検索する。
* 報酬を付与する ([AddUserVirtualCurrency](xref:titleid.playfabapi.com.server.playeritemmanagement.adduservirtualcurrency) の呼び出し)。
* 引き換え済みの報酬を更新する ([UpdateUserPublisherInternalData](xref:titleid.playfabapi.com.server.playerdatamanagement.updateuserpublisherinternaldata) の呼び出し)。
* 付与した金額を (CloudScript の return 文を介して) クライアントに提供する。

## まとめ

プレイヤーパブリッシャーデータとプレイヤーデータは、構造的には同一です。

プレイヤーデータは *タイトル固有* にすべきであり、プレイヤーパブリッシャーデータは *すべての* タイトルにわたって関連する情報 *のみ* を含むようにしてください。

## 関連項目

[Simple In-Game Cross Promotion](https://github.com/PlayFab/PlayFab-Samples/tree/master/Recipes/SimpleCrossPromotion): 複数のゲームに参加するプレイヤーに報酬を付与します。


## Related topics

- [プレイヤー データ](/ja-jp/services/playfab/player-progression/player-data/index.md)
- [パブリッシャー データの使用](/ja-jp/services/playfab/live-service-management/game-configuration/titledata/using-publisher-data.md)
- [XBOX の実績報酬の構成](/ja-jp/services/xbox-services/player-data/achievements/title-managed/concepts/live-achievement-rewards.md)
- [XR-014 プレイヤー データと個人情報](/ja-jp/publishing/certification/xr/xr-014.md)
- [XR-007 クロスネットワーク プレイ、データ使用、およびコンパニオン アプリ](/ja-jp/publishing/certification/xr/xr-007.md)
