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

# Azure Functions を利用した PlayFab CloudScript のクイックスタート ガイド

> Visual Studio Code と Unity を使って C# で Azure Functions を用いた PlayFab CloudScript を作成し、ルール、スケジュール タスク、またはクライアント呼び出しに関数をリンクします。

# クイックスタート: Azure Functions を使用した PlayFab CloudScript の作成

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

## 前提条件

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

* Visual Studio Code の [クイックスタート: Visual Studio Code を使用して Azure Functions プロジェクトを作成する](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp) を参照し、セットアップが完了したらここに戻ってください。次の前提条件は、そのクイックスタート ガイドでカバーされています:
  * [Azure アカウント](https://azure.microsoft.com/free)。Azure アカウントへのサインアップは無料です
  * [Azure サブスクリプション](https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/create-subscription)
  * Azure Portal で構成された Functions アプリ リソース
    * Azure Functions を利用した CloudScript のレイテンシを最小化するために、*US-West*、*US-West 2*、*US-West 3* の Azure リージョンに配置してください。
    * **セキュリティに関する注意:** セキュリティの観点から、特定の関数シークレットは PlayFab でのみ使用し、他のソースから同じ関数を呼び出すためには使用しないようにしてください。
    * **セキュリティに関する注意:** キュー関数については、キュー トリガーで使用するキュー用に別のストレージ アカウントを設定してください。
* [PlayFab](https://developer.playfab.com/) アカウント。

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

## Azure Function の作成

1. 基本的な「HelloWorld」サンプル関数を作成します。方法については、[Visual Studio Code を使用して最初の関数を作成するガイド](https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-first-function-vs-code) を参照してください。PlayFab 変数を使用するコード例については、[PlayFab 関数のコンテキスト、変数、およびサーバー SDK の使用](#playfabfunctioncontext) セクションを参照してください。

<Info>
  「Visual Studio Code を使用して最初の関数を作成する」ガイドでは、Azure Function の認可レベルを `Anonymous` に設定するよう指示されています。これはテストを簡略化するためです。本番環境ではほとんどの場合、匿名認可を使用すべきではありません。誰でも関数のエンドポイントを呼び出せるようになるためです。PlayFab 環境で関数を適切に保護するには、`Function` レベルの認可を使用することをお勧めします。
</Info>

2. 関数を作成してデプロイしたら、**Automation** > **Cloud Script** に移動し、ページ右上隅にある **Register Function** ボタンを選択します。

   <img src="https://mintcdn.com/microsoft-4404708b/dqv53299jA1M-fNi/images/playfab/live-service-management/service-gateway/automation/cloudscript-af/register_cs_function.png?fit=max&auto=format&n=dqv53299jA1M-fNi&q=85&s=4bfc5e2c33a1ad384fa01a0698d4cd5d" alt="Register CloudScript Function" width="542" height="549" data-path="images/playfab/live-service-management/service-gateway/automation/cloudscript-af/register_cs_function.png" />

3. **Name** には、関数の人にわかりやすい名前を入力します。**Function URL** には、関数の HTTP トリガー URL を入力します。URL は、[クイックスタート: Visual Studio Code を使用して Azure で関数を作成する](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-csharp?pivots=programming-language-csharp#run-the-function-in-azure) の「Run the function in Azure」セクションに示されているように、Azure Function リソースのコンテキスト メニューにあります。Azure Function が `Function` レベルの認可を使用している場合、URL には認可キーが含まれます。

Azure Functions のデプロイ方法の詳細については、[Visual Studio Code を使用した Azure Functions のデプロイ](https://learn.microsoft.com/azure/azure-functions/functions-develop-vs-code) を参照してください。

## PlayFab タイトルから Azure Functions を利用した CloudScript を使用および呼び出す

このガイドのサンプル コードは、Unity C# と Azure Function C# コードで記述されています。

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

### Visual Studio Code からの HTTP リクエストによる関数の呼び出し

[REST Client 拡張機能](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) を使用して、Visual Studio 内から関数を呼び出すことができます。

```http theme={null}
@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* 関数の下の *Send request* を選択してプレイヤーの entity token を取得し、次に *LoginWithCustomID* の下で関数を呼び出せます。*GetObjects* を呼び出すと、Azure Function がプレイヤーに関連付けたオブジェクトが表示されるはずです。

### Unity から関数を呼び出す

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

```c# theme={null}
//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 <a name="playfabfunctioncontext" />

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

1. Package Manager を使用して PlayFab SDK をインストールする必要があります。これを行うには、Visual Studio Code でターミナルまたは CMD コンソールを開き、次のように入力します: `dotnet add package PlayFabAllSDK`
2. `PlayFab.Samples` の実装を含む [CS2AFHelperClasses.cs](https://github.com/PlayFab/PlayFab-Samples/blob/master/Samples/CSharp/AzureFunctions/CS2AFHelperClasses.cs) ファイルをインクルードする必要があります
3. スクリプトの実行はいくつかの方法 (API、スケジュール タスク、PlayStream イベント、セグメントへの入退場メソッド) で行われます。CloudScript を実装する際は、実行のコンテキストが重要です。スクリプトのコンテキストの使用方法については、[CloudScript コンテキスト モデルの使用チュートリアル](/services/playfab/live-service-management/service-gateway/automation/cloudscript-af/CloudScript-af-context) を参照してください。

HelloWorld のサンプルを最初の Azure Function として使用できます。エンティティ API を呼び出し、認証されたプレイヤーに挨拶を返します。従来のサーバー API も同様の方法で呼び出せます。ただし、呼び出しを行うには title シークレット キーを指定する必要があります。シークレット キーは [アプリケーション設定](https://learn.microsoft.com/en-us/azure/azure-functions/functions-how-to-use-azure-function-app-settings?tabs=portal#settings) に保存し、`Environment.GetEnvironmentVariable()` メソッドを使用して取得できます。

```c# theme={null}
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 };
        }
    }
}
```

このサンプルでは、従来の CloudScript の実装と同様に、呼び出し元の `CurrentPlayerId` を利用できます。`FunctionParameters` フィールドで渡したパラメーターは *args* で利用可能です。ただし、[Visual Studio Code を使用して最初の関数を作成するガイド](https://learn.microsoft.com/en-us/azure/azure-functions/create-first-function-vs-code-csharp) の Hello World サンプルとは異なり、パラメーターはクエリ文字列ではなく POST ボディで渡されます。

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

## 自動化ルールでの Azure Functions

Azure Functions は、ルールおよびスケジュール タスクを作成して呼び出すこともできます。これは標準の CloudScript と同じように動作します。ルールまたはスケジュール タスクを作成するには、**Automation** > **Rules** または **Automation** > **Scheduled Tasks** に移動します。

* **New Rule** を選択します
* ルールの名前を入力します
* このルールがトリガーとするイベントの種類を選択します
* アクションを追加します
* アクションのドロップダウンから **Execute Azure Function** を選択します

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

<img src="https://mintcdn.com/microsoft-4404708b/dqv53299jA1M-fNi/images/playfab/live-service-management/service-gateway/automation/cloudscript-af/azure_function_rules.png?fit=max&auto=format&n=dqv53299jA1M-fNi&q=85&s=f48a4376587a492bd3dcbf1efa86c666" alt="Configure Rule for Azure Functions" width="800" height="966" data-path="images/playfab/live-service-management/service-gateway/automation/cloudscript-af/azure_function_rules.png" />

## Azure Function のデバッグ

Azure Functions では、CloudScript をローカルまたは Azure Portal でデバッグできるオプションが利用できるようになりました。Portal でのデバッグの詳細については、[Azure Portal を使用した Azure Functions による CloudScript のデバッグ](/services/playfab/live-service-management/service-gateway/automation/cloudscript-af/debugging-with-CloudScript-AF-Azure) を参照してください。ローカル デバッグのセットアップ方法については、[Azure Functions を利用した CloudScript のローカル デバッグ](/services/playfab/live-service-management/service-gateway/automation/cloudscript-af/local-debugging-for-cloudscript-using-azure-functions) を参照してください。

## 実行の制限

Azure Functions への CloudScript 呼び出しにはタイムアウト制限があります。Webhook の実行に時間がかかりすぎると、PlayFab でリクエストがタイムアウトします。コードがタイムアウト制限内に十分高速に実行できるようにしてください。

| ソース           | アクションの種類   | 制限 (秒) |
| ------------- | ---------- | -----: |
| PlayFab API   | HTTP リクエスト |     10 |
| PlayStream V2 | HTTP リクエスト |     10 |
| スケジュール タスク    | HTTP リクエスト |    4.5 |
| PlayStream V1 | HTTP リクエスト |      1 |
| キュー関数         | キューのペイロード  |      1 |
