自動化

【PlayFab】Azure Functionsをローカルでデバッグする方法

playfab-local-debug

この記事では、PlayFab で Azure Functions をローカルでデバッグする方法について解説していきます。

「え?何の話?」という状態の人は、CloudScriptでAzure Functionsを実行する方法を参照してからまた戻ってきてください。

ローカルデバッグについては詰まりポイントが多く、ゼロから調べてやると挫折してしまう可能性が高いです。

この記事では、挫折ポイントを先回りして解決しているので、スムーズにデバッグ作業に映ることができます。

では、さっそく見ていきましょう。

Azure Functions をローカルでデバッグする方法

ローカルデバッグの概念

まずはじめに、ローカルデバッグの概念について理解していきましょう。

簡単な図を作成してみました。

Unity側から Azure Functions を呼び出すと、Azureに登録されている関数が呼び出される、というのは通常の動きですね。

ここでは「通常モード」と呼ぶことにします。

ねこじょーかー
ねこじょーかー
厳密にはCloudScript経由でAzure Functions を呼び出しているのですが、画像を簡略化するために割愛しています!

通常モードとは別に、Azure Functions として登録する前でも、ローカルサーバーとしてデバッグして実行結果を確認することもできます。

ここでは「デバッグモード」と呼ぶことにします。

通常モードの場合でもデバッグできる、という話を聞いたのですが、知識不足でこのやり方はわかっていません。

この記事ではデバッグモードにフォーカスして解説をしていきます。

通常モードとデバッグモードの違い

デバッグモードのときにも、ローカルのHelloWorld関数を自動で呼び出してくれればいいのですが、そうはいきません。

というのも、通常モードとデバッグモードでは、発行されるURLが異なるためです。

URLの違い

HelloWorld関数を呼び出した場合

通常モード
  • https://test.azurewebsites.net/api/HelloWorld が呼び出される
  • 呼び出す関数名によってURLは変わる
デバッグモード
  • http://localhost:7071/api/CloudScript/ExecuteFunction が呼び出される
  • 関数名を変えても、必ずこのURLになる

上記の通り。

通常モードの場合、関数によってURLが変わります。

しかし、デバッグモードの場合は、URLが固定で発行されるため、普通にデバッグしようと思ってもURLが見つからずエラーとなります。

なんだ、デバッグできないのか…

諦めるのはまだ早いです。

ExecuteFunction関数を用意してあげて、そこからHelloWorld関数を呼び出すと、デバッグすることができることを確認しました。

次からはこの方法について解説していきます。

Azure Functions Core Tools のインストール

ソースコードを触る前に、Azure Functions Core Tools のインストールを参考にして、デバッグに必要なツールをインストールしましょう。

Azure Functions Core Tools のインストール」という段落だけ作業できれば問題ありません。

バージョンは v4.x を想定しています。

ツールの準備はこれで終了です。

ExecuteFunction関数の準備

ペンギンくん
ペンギンくん
でも、デバッグ用に関数を準備するのは大変そうだね。

私も同じことを思い、諦めようかなと考えました。

が、調べに調べ、なんとかExecuteFunctionのサンプルに出会うことができました。

上記ソースコードをコピーして、次に進んでください。

定数の準備

まずはじめに目に留まるのはこの3行。

private const string DEV_SECRET_KEY = "PLAYFAB_DEV_SECRET_KEY";
private const string TITLE_ID = "PLAYFAB_TITLE_ID";
private const string CLOUD_NAME = "PLAYFAB_CLOUD_NAME";

クラウド名はなくても動作したのでよくわかりませんが、シークレットキーとタイトルIDの設定は必要です。

以下から確認することができます。

ねこじょーかー
ねこじょーかー
定数を自分の値に書き換えるだけでしょ。楽勝。

と思っていたのですが、実際の処理を見ると、定数から環境変数を取り出すという処理をしていることに気づきました。

string title = Environment.GetEnvironmentVariable(TITLE_ID, EnvironmentVariableTarget.Process);
var secretKey = Environment.GetEnvironmentVariable(DEV_SECRET_KEY, EnvironmentVariableTarget.Process);

なので、定数に直接自分の値を入れるのではなく、環境変数として登録して上げる必要があります。

Azure Functions を使うときの環境変数の設定方法は、Azure Functionsで環境変数を設定する方法を参照してください。

これで定数の準備は完了です。

ローカルデバッグを有効化する(Visual Studio)

Visual Studio Code を使用している人は、この後の「Enable local debugging」という手順でファイルが自動生成されるので、手動で作成して配置する必要はありません。

デバッグをするには、playfab.local.settings.json というファイルを作成して、所定のフォルダに配置する必要があります。

以下の内容でファイルを作成しましょう。

playfab.local.settings.json
{ "LocalApiServer": "http://localhost:7071/api/" }

あとはこのファイルを所定のフォルダに置くのですが、Mac と Windows で場所が変わります。

Mac の人は、以下のコマンド「TMPDIR」というフォルダを開き、ファイルを配置してください。

open $TMPDIR

Windows の人は、「TEMP」というフォルダを開き、ファイルを配置してください。

具体的な手順は、Windows 10 ユーザーのTempフォルダー(一時フォルダ)を開く方法が参考になりそうです。

これでようやくExecuteFunctionの準備が整いました。

ローカルデバッグを有効化する(Visual Studio Code)

Visual Studio Code を使用する場合は、手動で playfab.local.settings.json を作成しなくても、以下の操作でファイルを生成できます。

  1. 左のPlayFabアイコンをクリック
  2. 反映したいタイトルを右クリック
  3. Enable local debuggingをクリック

ローカルデバッグを開始する

F5で実行して30秒くらいすると、ターミナルが以下の状態になります。

この状態になったら、あとはUnityから実行してみましょう。

デバッグをすると、まず最初にExecuteFunctionが実行されます。

ExecuteFunctionを経由して、ローカルのHelloWorld関数が呼び出されます。

実行後は、通常モードと同様に同じようなログが出力されることが確認できます。

これでひと通りの作業は完了です。

M1 MacのVisual Studio で実行したときに、次のエラーが出ることがあります。

System.Private.CoreLib: Exception while executing function: ExecuteFunction. PlayFabAllSDK: Invalid JSON string (Parameter 'json').

デバッグで追ってみると、ExecuteFunction.cs の GetHostRoutePrefix にて、host.json のデシリアライズで落ちていることがわかります。

なので、デシリアライズしている部分をコメントアウトして、_defaultRoutePrefix を固定で返すようにすると、エラーなく動作します。

private static string GetHostRoutePrefix()
{
    string hostFileContent = null;
    string currDir = Directory.GetCurrentDirectory();
    string currDirHostFile = Path.Combine(currDir, "host.json");

    if (File.Exists(currDirHostFile))
    {
        hostFileContent = ReadAllFileText(currDirHostFile);
    }

    // ↓ここをコメントアウト
    // var hostModel = PluginManager.GetPlugin<ISerializerPlugin>(PluginContract.PlayFab_Serializer).DeserializeObject<HostJsonModel>(hostFileContent);
    // return hostModel?.extensions?.http?.routePrefix ?? _defaultRoutePrefix;

    // ↓ここを追記
    return _defaultRoutePrefix;
}

ローカルデバッグをやめる

ローカルデバッグをやめるときは、先ほど配置した playfab.local.settings.json を削除してください。

Visual Studio Code を使用している人は、「Enable local debugging」の下の「Disable local debugging」という操作をすることでも、「playfab.local.settings.json」 を削除することができます。

playfab-local-debug

まとめ

Azure Functions をローカルでデバッグする方法について解説しました。

3行でまとめると以下のとおりです。

ローカルデバッグの方法まとめ
  1. Azure Functions Core Tools をインストール
  2. ExecuteFunction 関数の用意
  3. デバッグする

ゼロから調べると大変ですが、この記事を見ながらやればそこまで時間はかからないはずです。

毎回 Azure にアップロードして実行するのも面倒ですからね。

PlayFab では現状、Azure Functions を使わないとデバッグができないので、ぜひこの機会に Azure Functions を導入してみましょう。

PlayFab の書籍も好評発売中!
playfab-book

PlayFab のことをもっと皆さんに知ってもらいたくて、合計500ページ以上にもなる書籍を5冊に分けて執筆しました。

私の知識をすべて詰め込んでいるので、ゲーム開発をさらに加速させたい方はぜひご覧ください。

POSTED COMMENT

  1. 新一 より:

    前回、質問させていただいたバイナリデータと画像の件は、上手くいきました!ありがとうございます!

    今回、ガチャを実装しようと思って、ねこじょーかーさんのサイトのドロップアイテムを見て作ろうと思ったのですが、まず、Azure関数を使うということで、環境設定等を試みました。そこは、おそらく突破できたのですが、HelloWorldでできるか試そうとしたところ、VScodeでHelloWorldのAzure関数内で、現在のコンテキストにFunctionContextという名前は存在しません。というエラーが出てしまいました。探して解決しようと思いましたが、策が見つからず質問させていただきました。解答よろしくお願いします。

    • ねこじょーかー より:

      新一さん、こんばんは!
      前回の件はうまくいったとのことで、安心しました!

      今回は FunctionContext のクラスが見つからない、ということですね。
      パッと思いつくのは以下の2点です。

      ■正しくパッケージ追加ができているか
      FunctionContext は「PlayFab.Plugins.CloudScript」の名前空間のクラスです。
      なので、そもそもこの名前空間を参照できない場合は、
      パッケージ追加がうまくいっていない可能性が高いです。

      以下の記事を参考に、もう一度環境を確認してみてください。
      https://playfab-master.com/playfab-azure

      ■公式のサンプルで試していないか
      公式ドキュメントの HelloWorld のサンプルは「FunctionExecutionContext」というクラスになっており、
      「PlayFab.Samples」の参照が必要になってきます。

      上記ではなく、以下の記事の HelloWorld を試してみてください。
      https://playfab-master.com/playfab-azure-cloudscript

      上記が問題ないという場合、あとは VSCode を再起動してみるとか、それくらいでしょうか…

      • まく より:

        いつも参考にさせていただいております。
        私も同じ現象が起きております。いろいろ試したのですが、うまくいかず
        ご存じであればご教示いただけないでしょうか。
        環境として、M1Macで構築しているのですが、M1では.NETCore3.1をサポートしておらず、.NETCORE6.0をインストールしました。
        FunctionContextは.NETCore3.1以下で動作するものでしょうか。

        • ねこじょーかー より:

          まくさん、こんにちは!
          ブログをご覧いただきありがとうございます。

          私も最近 M1 にしたばかりで試せていませんが、M1 でも .NET Core 3.1 はインストールできます。
          以下のページを参考に試してみてください。
          https://docs.microsoft.com/ja-jp/visualstudio/mac/uninstall-net-2019?view=vsmac-2019

          また、.NET 6 については以前試してみましたが、Azure Functions Core Tools がまだ正式に対応されていないようで、うまく動作しませんでした。
          以下に Issue が登録されていて、これがクローズされれば .NET 6 でも動作するようになると思います!
          https://github.com/Azure/azure-functions-core-tools/issues/2834

          • まく より:

            早々にご回答いただきありがとうございます!
            無事、 .NET Core 3.1のインストールができました!
            ですが、状況変わらず下記のようにエラーとなります。

            型または名前空間の名前 ‘FunctionExecutionContext’ が見つかりませんでした (using ディレクティブまたはアセンブリ参照が指定されていることを確認してください)。

            やはり上で言われているように、パッケージ追加がうまくいってないのですかね。。
            もう少し試してみます。
            ちなみに下記記事を参考にさせていただき実装しているのですが、この場合は「CS2AFHelperClasses.cs」のクラスを参照しなくて問題ないでしょうか?
            「using PlayFab.Samples;」とした場合も試したのですが、今度は「’FunctionExecutionContext’ に ‘ApiSettings’ の定義が含まれていない」とエラーがでてしまったので今は外してあります。

          • ねこじょーかー より:

            まくさん
            .NET Core 3.1 のインストールができたとのことで、よかったです!
            エラーの原因はわかりませんが、最初に .NET 6 でプロジェクトを作成していると思いますので、.NET Core 3.1 で作り直したほうがいいかもしれません。

  2. えす より:

    項目「ローカルデバッグをする」の作業をした際にvscode側で
    「PowerShellでこのシステムではスクリプトの実行が無効になっているため、ファイル hoge.ps1 を読み込むことができません。」
    というエラーが出た際は以下のサイトを参考に実行ポリシーを変更することでうまくいきました。
    https://qiita.com/ponsuke0531/items/4629626a3e84bcd9398f

    • ねこじょーかー より:

      なんと、そんな現象もあるんですね。
      コメントをくださり、ありがとうございます〜!

新一 へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。