クイックスタート: Azure Functions を使用して PlayFab CloudScript を記述する

このクイック スタートでは、Visual Studio Code、Azure Functions C# および Unity C# で Azure Functions を使用して CloudScript を記述します。 このガイドを完了すると、新しい CloudScript をルール、スケジュールされたタスクにリンクしたり、クライアント コードから呼び出したりさえできるようになります。

前提条件

PlayFab C# CloudScript の使用を開始するには、いくつかの手順が必要です。

  • Visual Studio Code 「QuickStart: Visual Studio Code を使用してAzure Functions プロジェクトを作成」にアクセスし、設定し終わったらここに戻ります。 クイックスタート ガイドでは、次の前提条件について説明します。
    • Azure アカウント。 Azure アカウントへのサインアップは無料です
    • Azure サブスクリプション
    • Azure portal で構成された関数アプリの リソース
      • Azure Functions 使用して CloudScript の待機時間を最小限に抑えるには、米国西部米国西部 2米国西部 3のいずれかの Azure 地域で配置します。
      • セキュリティに関する注意: セキュリティの観点からは、PlayFab で特定の関数シークレットのみを使用し、他のソースから同じ関数を呼び出すために使用しないようにする必要があります。
      • セキュリティ に関する注意: キューに登録された関数の場合は、キュー トリガーに使用されるキューに対して個別のストレージ アカウントを設定する必要があります。
  • PlayFab アカウント。

注意

PlayFab Azure Functions では、Azure Functions V2 ランタイム以上、および .NET Core 2 以上を使用できます。 最新バージョン (現在は Azure Functions V4 と .NET 6) を使用することをお勧めします。

Azure 関数を作成する

  1. 基本的な "HelloWorld" サンプル関数を作成します。 これを行う方法については、「Visual Studio Code を使用して最初の関数を作成する」ガイドに従ってください。 PlayFab 変数を使用するコード例については、以下のセクション PlayFab 関数コンテキスト、変数、およびサーバー SDK の使用に関するセクションを参照してください。

    Important

    「Visual Studio Code を使用して最初の関数を作成する」ガイドでは、Azure 関数の承認レベルを Anonymousに設定するように指示されています。 これは、テストを簡略化するために行われます。

    運用環境では、ほとんどの場合、匿名承認を使用しないでください。これは、誰でも関数エンドポイントを呼び出せるためです。 PlayFab 環境で関数を適切にセキュリティで保護するには、 Function レベルの承認を使用することをお勧めします。

  2. 関数を作成して展開したら、Automation>Cloud Script に移動し、ページの右上隅にある [関数の登録] ボタンを選択します。

    Register CloudScript 関数

  3. Nameには、分かりやすい関数の名前を入力します。 関数 URL には、関数の HTTP トリガー URL を入力します。 URL は、「QuickStart: Visual Studio Code を使用して Azure で関数を作成する」の「Azure で関数を実行する」セクションに示されているように、Azure 関数リソースのコンテキスト メニューにあります。 Azure 関数で Function レベルの承認が使用されている場合、URL には承認キーが含まれます。

Azure 関数のデプロイの詳細については、「Visual Studio Code から Azure Functions をデプロイする」を参照してください。

Azure Functions を使用して PlayFab タイトルから CloudScript を使用して呼び出す

このガイドのコード例は、Unity C# と Azure 関数 C# のコードで記述されています。

関数が登録されたので、PlayFab API を使用してその関数を内部から呼び出すことができます。

Visual Studio Code からの HTTP 要求を使用して関数を呼び出す

REST クライアント拡張機能を使用すると、Visual Studio 内から関数を呼び出すことができます。

@titleId =  ????? # Enter your title ID here
@baseUrl = https://{{titleId}}.playfabapi.com

###
# @name LoginWithCustomID
POST {{baseUrl}}/Client/LoginWithCustomID
Accept-Encoding: gzip
Content-Type: application/json

{
  "CustomId": "demo",
  "CreateAccount": true,
  "TitleId": "{{titleId}}"
}

@entityToken = {{LoginWithCustomID.response.body.$.data.EntityToken.EntityToken}}
@entity = {{LoginWithCustomID.response.body.$.data.EntityToken.Entity}}

###
# @name ExecuteFunction
POST {{baseUrl}}/CloudScript/ExecuteFunction
Accept-Encoding: gzip
Content-Type: application/json
X-EntityToken: {{entityToken}}

{
  "FunctionName": "HelloWorld"
}

###
# @name GetObjects
POST {{baseUrl}}/Object/GetObjects
Accept-Encoding: gzip
Content-Type: application/json
X-EntityToken: {{entityToken}}

{
  "Entity": {{entity}},
  "Objects": ["obj1"]
}

このコードを .http 拡張子を持つ Visual Studio Code 内のファイルに貼り付けた後、LoginWithCustomID 関数で [要求の送信] を選択 してプレイヤーのエンティティ トークンを取得し、LoginWithCustomID で関数を呼び出すことができます。 GetObjects を呼び出すと、Azure 関数によってプレイヤーにアタッチされたオブジェクトが表示されます。

Unity から関数を呼び出す

Unity でこのコードを使用して、関数を呼び出すことができます。

//This snippet assumes that your game client is already logged into PlayFab.

using PlayFab;
using PlayFab.CloudScriptModels;

private void CallCSharpExecuteFunction()
{
    PlayFabCloudScriptAPI.ExecuteFunction(new ExecuteFunctionRequest()
    {
        Entity = new PlayFab.CloudScriptModels.EntityKey()
        {
            Id = PlayFabSettings.staticPlayer.EntityId, //Get this from when you logged in,
            Type = PlayFabSettings.staticPlayer.EntityType, //Get this from when you logged in
        },
        FunctionName = "HelloWorld", //This should be the name of your Azure Function that you created.
        FunctionParameter = new Dictionary<string, object>() { { "inputValue", "Test" } }, //This is the data that you would want to pass into your function.
        GeneratePlayStreamEvent = false //Set this to true if you would like this call to show up in PlayStream
    }, (ExecuteFunctionResult result) =>
    {
        if (result.FunctionResultTooLarge ?? false)
        {
            Debug.Log("This can happen if you exceed the limit that can be returned from an Azure Function, See PlayFab Limits Page for details.");
            return;
        }
        Debug.Log($"The {result.FunctionName} function took {result.ExecutionTimeMilliseconds} to complete");
        Debug.Log($"Result: {result.FunctionResult.ToString()}");
    }, (PlayFabError error) =>
    {
        Debug.Log($"Opps Something went wrong: {error.GenerateErrorReport()}");
    });
}

PlayFab CloudScript のコンテキスト、変数、およびサーバー SDK

Azure Functions を使用して CloudScript を使用する利点の 1 つは、PlayStream イベントとプレイヤー プロファイルのコンテキストが Azure 関数に自動的に渡される点です。 CloudScript の呼び出し時に、関数の呼び出しシナリオに従ってコンテキストを受け取ります。 たとえば、コンテキストは、PlayStream アクションによってトリガーされたか、クライアントから直接呼び出されたかによって異なります。 これには、CloudScripts の代わりに呼び出されたエンティティ プロファイルや、CloudScript の呼び出しに使用される PlayStream イベントなどの情報が含まれます。

  1. パッケージ マネージャーを使用して PlayFab SDK をインストールする必要があります。 これを行うには、Visual Studio Code でターミナルまたは CMD コンソールを開き、次のように入力します: dotnet add package PlayFabAllSDK
  2. PlayFab.Samples の実装を含む CS2AFHelperClasses.cs ファイルを含める必要があります。
  3. スクリプトは、複数のメソッド (API、スケジュールされたタスク、PlayStream イベント、セグメントの開始および終了メソッド) を使用して実行できます。 CloudScript を実装するには、実行のコンテキストが重要です。 スクリプトのコンテキストの使用方法の詳細については、「CloudScript コンテキスト モデルの使用に関するチュートリアル」を参照してください。

最初の Azure 関数として、以下の HelloWorld の例を使用できます。 エンティティ API を呼び出し、認証されたプレイヤーに案内応答を返します。 クラシック サーバー API は、同様の方法で呼び出すことができます。ただし、呼び出しを行うには、タイトルの秘密鍵を指定する必要があります。 秘密鍵は、アプリケーション設定に格納し、Environment.GetEnvironmentVariable() メソッドを使用して取得できます。

using PlayFab;
using PlayFab.Samples;
using PlayFab.DataModels;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace PlayFabCS2AFSample.HelloWorld
{
    public static class HelloWorld
    {
        [FunctionName("HelloWorld")]
        public static async Task<dynamic> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            FunctionExecutionContext<dynamic> context = JsonConvert.DeserializeObject<FunctionExecutionContext<dynamic>>(await req.ReadAsStringAsync());

            dynamic args = context.FunctionArgument;

            var message = $"Hello {context.CallerEntityProfile.Lineage.MasterPlayerAccountId}!";
            log.LogInformation(message);

            dynamic inputValue = null;
            if (args != null && args["inputValue"] != null)
            {
                inputValue = args["inputValue"];
            }

            log.LogDebug($"HelloWorld: {new { input = inputValue} }");

            // The profile of the entity specified in the 'ExecuteEntityCloudScript' request.
            // Defaults to the authenticated entity in the X-EntityToken header.
            var entityProfile = context.CallerEntityProfile;

            var api = new PlayFabDataInstanceAPI(
                new PlayFabApiSettings
                {
                    TitleId = context.TitleAuthenticationContext.Id
                },
                new PlayFabAuthenticationContext
                {
                    EntityToken = context.TitleAuthenticationContext.EntityToken
                }
            );

            var apiResult = await api.SetObjectsAsync(
                new SetObjectsRequest
                {
                    Entity = new EntityKey
                    {
                        Id = entityProfile.Entity.Id,
                        Type = entityProfile.Entity.Type
                    },
                    Objects = new List<SetObject> {
                    new SetObject
                    {
                        ObjectName =  "obj1",
                        DataObject = new
                        {
                            foo = "some server computed value",
                            prop1 = "bar"
                        }
                    }
                }
                });

            return new { messageValue = message };
        }
    }
}

この例では、呼び出し元の CurrentPlayerId は、従来の CloudScript 実装と同様に使用できます。 FunctionParameters フィールドに渡すパラメーターは、args で使用できます。 ただし、「Visual Studio Code を使用して最初の関数を作成する」ガイドの Hello World サンプルとは異なり、パラメーターは、クエリ文字列ではなく POST 本文で渡されます。

PlayFab SDK から HelloWorld の Azure 関数を呼び出すには、ExecuteFunctionを使用します。

Automation ルールの Azure Functions

Azure Functions は、ルールとスケジュールされたタスクを作成して呼び出すこともできます。 これは、標準の CloudScript と同じように機能します。 ルールまたはスケジュールされたタスクを作成するには [自動化]>[ルール] に移動するか、[自動化]>[スケジュールされたタスク] に移動します。

  • [新しいルール] を選択します。
  • ルールの名前を入力する
  • このルールがトリガーされるイベントの種類を選択します
  • アクションを追加する
  • [アクション] ドロップダウンから [Azure 関数の実行] を選択する

登録した使用可能な Azure Functions の一覧がドロップダウン リストに表示されます。

Azure Functions のルールを構成する

Azure 関数をデバッグする

Azure Functions では、CloudScript をローカルまたは Azure portal でデバッグできるようになりました。 ポータルのデバッグの詳細については、「Azure portal で Azure Functions を使用して CloudScriptをのデバッグする」を参照してください。 ローカル デバッグを設定する方法については、「Azure Functions を使用した Cloudscript のローカル デバッグ」を参照してください。

実行制限

Azure Functions への CloudScript 呼び出しにはタイムアウト制限があります。 Webhook の実行に時間がかかりすぎると、要求は PlayFab でタイムアウトします。 タイムアウト制限内に収まるようコードを速く実行できることを確認します。

ソース アクションの種類 制限 (秒)
PlayFab API HTTP 要求 10
PlayStream V2 HTTP 要求 10
スケジュール済みタスク HTTP 要求 4.5
PlayStream V1 HTTP 要求 1
キュー関数 キュー ペイロード 1