目次

まえがき

第1章 ドロップテーブルを使おう

1.1 ドロップテーブルとは
1.2 ドロップテーブル用のアイテムを登録する
1.3 ドロップテーブルを登録する
1.4 アイテムをドロップする
1.5 自前でドロップ処理を実装する
1.6 ドロップテーブルの確率を取得する
1.7 バンドルを使用したドロップテーブル

第2章 タイトルニュースを使おう

2.1 タイトルニュースの概要
2.2 タイトルニュースの登録
2.3 タイトルニュースを取得する
2.4 タイトルニュースをローカライズする
2.5 本文をJSONで管理しよう

第3章 メールを送信しよう

3.1 メール送信の準備
3.2 メールを送信する(メール確認)
3.3 メールを送信する(カスタム)

第4章 フレンド機能を使おう

4.1 フレンドとは
4.2 他のプレイヤーを検索する
4.3 他のプレイヤーをフレンドに追加する
4.4 フォローまたはフォロワーを一覧表示する
4.5 他のプレイヤーをフレンドから削除する

第5章 キャラクターを使おう

5.1 キャラクターとは
5.2 クライアントからキャラクターを付与する
5.3 サーバーからキャラクターを付与する
5.4 キャラクターに関する各種API

第6章 エンティティを使おう

6.1 エンティティとは
6.2 クラシックAPIとの対応
6.3 エンティティのイメージ
6.4 エンティティを操作する(タイトルプレイヤー)
6.5 エンティティを操作する(マスタープレイヤー)
6.6 エンティティデータを操作する(タイトル)
6.7 エンティティを操作する(キャラクター)
6.8 エンティティを操作する(パブリッシャー)
6.9 エンティティを操作する(グループ)

第7章 エンティティグループを使おう

7.1 エンティティグループとは
7.2 エンティティグループを作成する
7.3 エンティティグループに招待する
7.4 エンティティグループに参加申請する
7.5 その他のAPI

あとがき

まえがき

 本書を手に取っていただき、ありがとうございます。本書の中では、エンティティの使い方について触れています。エンティティは、PlayFabにおけるデータ管理の新しい考え方で、実際に試している人は見つけられず、情報がほとんどありませんでした。そんな中でも諦めず、試行錯誤を繰り返して、何とか本書の完成にまでたどり着くことができました。本書には、検索しても簡単に見つからない情報を惜しみなく載せています。誰かが作成したもののコピーコンテンツではありません。私が独自に調べ、試して、本書にまとめています。私と同じことを調べようとすると、みなさんも何十時間もかけてしまうことになります。その時間は本当にもったいないです。なぜなら、本書を読むことでその分の時間を開発に回すことができるからです。本書の値段分は、1日もかからずに元が取れる内容だと確信しています。日本では誰も発信していない内容なので、値段の10倍くらいの価値があると自負しています。PlayFabを採用するからには、実装コストを下げたいと考えていることでしょう。本書をお読みになって、どんどん開発を加速させてください。あなたがやりたいことは、PlayFabの使い方を時間をかけて調べることではなく、ゲームをできるだけ早く完成させることです。私は、そのお手伝いができます。

 いろいろとつまづきながら学習した経験から、つまずくポイントもわかっています。つまずく点を先回りして解決できるよう、画像も多めに使用し、わかりやすさと見やすさにこだわって書きました。この本を読むことで、PlayFabにかける勉強時間を少なくして、ゲーム開発の部分に時間を割くことができます。この本が、少しでもみなさんのためになれば幸いです。

 PlayFabのことを教えてくださった方々、普段の発信をシェアしたりコメントしてくださる方々、応援してくださる方々のおかげで、本書の執筆にいたることができました。深く感謝いたします。

ねこじょーかー

本書の目的

 本書の目的は、PlayFabの基礎とサーバー処理の実装方法を理解している人が、ドロップテーブルやフレンドなど、ソーシャル機能を中心に、ひと通り使えるようになることです。特に、エンティティまわりについては情報が少なく、ゼロから調べるのは大変ですが、本書でわかりやすく解説しているので、迷うことなく進められると思います。PlayFabの基本機能をひと通り網羅したい人にとって、この本はぴったりです。

本書で得られること

 ・ドロップテーブルの知識

 ・タイトルニュースの知識

 ・メール送信の知識

 ・フレンドの知識

 ・キャラクターの知識

 ・エンティティの知識

 ・エンティティグループの知識

対象読者

 ・PlayFabの基礎学習、サーバー処理の勉強が終わっている人

 ・ソーシャルまわりの機能に興味がある人

 ・普段からPlayFabを使っているが、復習も兼ねて学びたい人

前提知識

 本書は、以下の知識がある前提とします。UnityやC#の説明は省き、PlayFabに特化した説明をしています。

 ・PlayFabの基礎知識(入門編の内容が理解できていること)

 ・サーバー処理の基礎知識(自動化編の内容が理解できていること)

使用したソフトウェアのバージョン

 本書では、以下のバージョンを使用しています。PlayFabSDKは最新のバージョンを使用して構いません。Unityのバージョンも、特に揃える必要はありません。

 ・Unity 2019.4.1f1

 ・PlayFab SDK 2.89.200629

 ・PlayFabAllSDK 1.77.200730



第1章 ドロップテーブルを使おう

 PlayFabでは、アイテムごとに確率を付けて、その確率ごとにドロップすることができる「ドロップテーブル」の機能が提供されています。本章では、ドロップテーブルの概要と使い方について解説します。

1.1 ドロップテーブルとは

 ドロップテーブルとは、アイテムごとに確率をもたせてひとつのテーブルとして管理することで、その確率に応じてランダムにアイテムを取得できる機能のことです。ひとつの使い方の例としては、ガチャの機能を実現できます。たとえば、プレイヤーがゲーム内通貨を消費することでガチャを引き、確率に応じてモンスターを手に入れることができるという機能ですね(図1.1)。また、クエストのクリア報酬として付与するアイテムも、8割は通常アイテムをドロップして、2割はレアアイテムをドロップする、という使い方も可能です。

図1.1: ドロップテーブルのイメージ

1.2 ドロップテーブル用のアイテムを登録する

 ドロップテーブルを使用するには、まずアイテムが必要になります。私は、図1.2の内容で登録しました。ここは、何でも好きなアイテムで構いません。

図1.2: 登録したアイテム

1.3 ドロップテーブルを登録する

 アイテムが登録できたら、ドロップテーブルを登録します。「エコノミー > カタログ > ドロップテーブル」と進み、「新しいドロップテーブル」を選択してください(図1.3)。

図1.3: 新しいドロップテーブル

 テーブルIDを入力した後、「ドロップテーブルを追加」を選択しましょう(図1.4)。図1.5が表示されるので、そこから先ほど登録したアイテムを選択すると、図1.6の状態になります。

図1.4: テーブルIDの入力
図1.5: ドロップテーブルにアイテムを追加

 加重というのは、そのアイテムが全体のどれだけの比率でドロップするかを表す数値のことです。加重が大きければ大きいほど、ドロップ率が上がります。隣に表示されている「オッズ」というのが、ドロップ率のことです。好きな加重を入力した後は、「ドロップテーブルを保存」を選択してください。これで、ドロップテーブルの保存が完了しました。

図1.6: 加重を入力してドロップテーブルを保存する

1.4 アイテムをドロップする

サーバー処理の実装

 「アイテムをひとつドロップする」というケースを見てみましょう。ドロップテーブルに従ってアイテムをひとつドロップするには、EvaluateRandomResultTable1を使用します。TableIdとCatalogVersionが必要になるので、クライアント側から引数で渡してあげましょう。結果は、ResultItemIdというプロパティで取得できます。アイテムのドロップができたので、GrantItemsToUser2を使用して、プレイヤーにアイテムを付与します。最後に、付与結果をクライアント側に返して、ひと通りの処理が完了です。

リスト1.1: アイテムをドロップするサーバー処理

[FunctionName("DropItem")]
public static async Task<dynamic> DropItem(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
    string body = await req.ReadAsStringAsync();
    log.LogInformation($"Body : {body}");
    var context = JsonConvert
                  .DeserializeObject<FunctionExecutionContext<dynamic>>(body);
    var args = context.FunctionArgument;
    string playFabId = context.CallerEntityProfile.Lineage.MasterPlayerAccountId;
    var serverApi = GetServerInstance(context.TitleAuthenticationContext);

    var evaluateResult = await serverApi.EvaluateRandomResultTableAsync(new EvaluateRandomResultTableRequest
    {
        TableId = args["TableId"],
        CatalogVersion = args["CatalogVersion"]
    });

    var grantResult = await serverApi.GrantItemsToUserAsync(new GrantItemsToUserRequest
    {
        PlayFabId = playFabId,
        CatalogVersion = args["CatalogVersion"],
        ItemIds = new List<string> { evaluateResult.Result.ResultItemId }
    });

    return new
    {
        error = PlayFabSimpleJson.SerializeObject(grantResult.Error),
        result = PlayFabSimpleJson
                 .SerializeObject(grantResult.Result.ItemGrantResults)
    };
}

クライアント側の実装

 クライアントから呼び出すときは、TableIdとCatalogVersionを引数で渡します。サーバー側の返り値としてはList<GrantedItemInstance>を指定しているのですが、クライアント側では指定することができません。そこで、List<ItemInstance>を代わりに指定しています。問題なく実行できると、リスト1.4の結果が返ってきます。今回は、みどりの魔物がドロップされたことが確認できました。

リスト1.2: アイテムをドロップする処理の呼び出し

private void DropItem()
{
    CallAzureFunctions<List<ItemInstance>>(
        "DropItem",
            new
            {
                CatalogVersion = "Main",
                TableId = "dt_normal"
            },
        funcResult =>
        {
            Debug.Log("アイテムドロップ成功!");
            Debug.Log(PlayFabSimpleJson.SerializeObject(funcResult));
        }, funcError =>
        {
            Debug.Log("実行時にエラーが発生しました。");
            Debug.Log(funcError.GenerateErrorReport());
        });
}

リスト1.3: Azure Functionsを呼び出す共通関数

/// <summary>
/// Azure Functions の呼び出し
/// </summary>
/// <typeparam name="T">取得結果の型</typeparam>
/// <param name="funcName">呼び出す関数名</param>
/// <param name="funcParam">サーバーに渡すパラメータ</param>
/// <param name="onSuccess">成功時コールバック</param>
/// <param name="onError">失敗時コールバック</param>
public void CallAzureFunctions<T>(
    string funcName,
    object funcParam,
    Action<T> onSuccess = null,
    Action<PlayFabError> onError = null)
{

    PlayFabCloudScriptAPI.ExecuteFunction(new
        PlayFab.CloudScriptModels.ExecuteFunctionRequest()
    {
        Entity = new PlayFab.CloudScriptModels.EntityKey()
        {
            Id = PlayFabSettings.staticPlayer.EntityId,
            Type = PlayFabSettings.staticPlayer.EntityType
        },
        FunctionName = funcName,
        FunctionParameter = funcParam,
        GeneratePlayStreamEvent = true,
    }, result =>
    {
        Debug.Log("Azure Functions 実行成功!");

        // 返り値の取り出し
        var jsonResult = (JsonObject)result.FunctionResult;
        var funcSuccess = PlayFabSimpleJson.DeserializeObject<T>
                                            (jsonResult["result"].ToString());
        var funcError = PlayFabSimpleJson.DeserializeObject<PlayFabError>
                                          (jsonResult["error"].ToString());

        if (result.FunctionResultTooLarge != null
            && (bool)result.FunctionResultTooLarge)
        {
            onError?.Invoke(funcError);
            return;
        }

        if (funcError == null)
            onSuccess?.Invoke(funcSuccess);
        else
            onError?.Invoke(funcError);
    }, error =>
    {
        onError.Invoke(error);
    });
}

リスト1.4: 実行結果

[
    {
        "Annotation": null,
        "BundleContents": null,
        "BundleParent": null,
        "CatalogVersion": "Main",
        "CustomData": null,
        "DisplayName": "みどりの魔物",
        "Expiration": null,
        "ItemClass": "Monster",
        "ItemId": "monster_green",
        "ItemInstanceId": "A4D0364CEB3E28F9",
        "PurchaseDate": "2020-09-14T12:51:36.219Z",
        "RemainingUses": 3,
        "UnitCurrency": null,
        "UnitPrice": 0,
        "UsesIncrementedBy": 1
    }
]

1. https://docs.microsoft.com/en-us/rest/api/playfab/server/player-item-management/evaluaterandomresulttable

2. https://docs.microsoft.com/en-us/rest/api/playfab/server/player-item-management/grantitemstouser

試し読みはここまでです。
この続きは、製品版でお楽しみください。