Actions Builder で Google アシスタント用の Interactive Canvas アクションを構築する

Actions on Google は、Google アシスタントのバーチャル パーソナル アシスタント機能を拡張してソフトウェアを作成できるデベロッパー プラットフォームです。スマート スピーカー、スマートフォン、自動車、テレビ、ヘッドフォンなど 10 億以上のデバイスに対応しています。ユーザーは、Google アシスタントとの会話を通じて、食料品の購入から乗車の予約までさまざまなタスクを実行できます(現時点で何を実行できるかについては、Actions ディレクトリの一覧をご覧ください)。Actions on Google を使用することで、独自のサードパーティ サービスを開発し、ユーザーとの便利で快適な会話型エクスペリエンスを簡単に作成、管理できます。

この Codelab は、Google アシスタントのアクションを構築した経験がある方を対象とする上級者向けのモジュールです。Actions on Google での開発経験がない場合は、入門編の Codelab(レベル 1レベル 2)で、プラットフォームの使い方を習得することを強くおすすめします。これらのモジュールでは、アクションの機能を拡張するためのさまざまな機能について説明しています。魅力的なアクションを構築し、新たなユーザーの獲得に役立ててください。

この Codelab では、Google アシスタント上に構築されたフレームワーク Interactive Canvas を使用して、会話型アクションに全画面のゲームを追加します。このゲームは、会話の中でアシスタントからユーザーに応答を送信するインタラクティブなウェブアプリです。ユーザーは、スマートディスプレイまたは Android モバイル デバイスを使用して、音声入力またはテキスト入力でゲームをプレイできます。

ゲームをゼロから構築するのではなく、すでに部分的に構築されている Snow Pal ゲームをデプロイし、Codelab を進めながらゲームのロジックを追加していきます。Snow Pal は、昔ながらの Hangman ゲームに少し手を加えたものです。出題される単語の各文字が空白で表示されており、プレーヤーはその単語にどの文字が含まれるかを推測します。回答した文字が 1 つも含まれていないと、Snow Pal(雪だるま)が少しずつ溶けます。雪だるまが完全に溶けてしまう前に単語が完成すればプレーヤーの勝ちです。

af9931bb4d507e39.png

図 1. プレイ途中の Snow Pal ゲーム。

目標

この Codelab では、Interactive Canvas を使用して、以下の機能を備えたアクションを構築します。

  • 音声でプレイできる全画面のワードゲーム
  • ユーザーがゲームを開始するためのボタン
  • ユーザーがゲームをもう一度プレイするためのボタン

この Codelab を完了すると、次のような会話フローのアクションが完成します。

アシスタント: Welcome to Snow Pal! Would you like to start playing the game?

ユーザー: Yes

アシスタント: Try guessing a letter in the word or guessing the word.

ユーザー: I guess the letter E

アシスタント: Let's see if your guess is there...E is right. Right on! Good guess.

ユーザーは、文字または単語自体の推測をゲーム終了まで繰り返します。

演習内容

  • Interactive Canvas アクションを構築してデプロイする
  • ユーザーの音声入力とクリック入力に基づいてワードゲームを更新する
  • さまざまな方法でウェブアプリにデータを渡す
  • Interactive Canvas アクションをデバッグする

必要なもの

この Codelab に必要なもの(および前提条件)は以下のとおりです。

  • ウェブブラウザ(Chrome など)
  • 任意の IDE またはテキスト エディタ
  • お使いのマシンに NodeJSnpmgit がインストールされていること

この Codelab で使用するコードを理解するうえで、JavaScript(ES6)に精通していることを強く推奨します。

完成したサンプルコードを取得する(省略可)

この Codelab では、未完成のサンプルコードに少しずつ変更を加えて完成させます。必要な場合は、完成したサンプルを GitHub リポジトリから入手することもできます。

Interactive Canvas は、会話型アクションに全画面の映像とアニメーションを追加できるようにするため、Google アシスタント上に構築されたフレームワークです。

Interactive Canvas を使用するアクションも、通常の会話型アクションと同じように機能します。ただし、Interactive Canvas アクションは追加機能を備えており、全画面のウェブアプリを開いているデバイスに対してレスポンスを送信できます。

ユーザーは、音声またはクリック操作によるウェブアプリへの入力を、会話が終了するまで繰り返します。

fa63a599f215aa81.gif

図 2. Interactive Canvas で構築したアクション。

この Codelab のプロジェクトは、次の 3 つの要素で構成されています。

  • ウェブアプリ: ウェブアプリ ファイルには、ウェブアプリの映像とアニメーションのコードと、ユーザー入力に基づいてウェブアプリを更新するためのロジックが含まれています。
  • 会話型アクション: 会話型アクションには、ユーザー入力を認識、処理し、それに応答する会話ロジックが含まれています。
  • Webhook: Webhook は、ゲームのロジックを処理します。この Codelab の Webhook は、ゲームサーバーの役割を果たすものと考えることができます。

この Codelab の各セクションでウェブアプリ、会話型アクション、Webhook に変更を加え、Interactive Canvas アクションに機能を追加していきます。

以下に、Snow Pal アクションの会話型アクション、Webhook、ウェブアプリの動作の概要をまとめます。

  1. 会話型アクションが、単語内の文字または単語自体を推測するようユーザーに促します。
  2. ユーザーが、スマートディスプレイの Snow Pal ウェブアプリに対して、「I guess the letter i」(文字 i は入ってる?)と言います。
  3. ユーザー入力が会話型アクションにルーティングされます。会話型アクションは、Actions Builder または Actions SDK プロジェクトで定義します。
  4. 会話型アクションがユーザー入力を処理し、入力の内容に応じて、ウェブアプリを更新する Webhook のロジックをトリガーするか、ウェブアプリを直接更新するためのメタデータを送信します。
  5. ウェブアプリが更新され、入力した文字が単語内のどこに出現するかが表示されます。その後、会話型アクションが再びユーザーに推測を促します。

Interactive Canvas の仕組みについて詳しくは、後述の「Interactive Canvas の構造を理解する」をご覧ください。ここまで、Codelab の基本について説明しました。次のセクションでは、Codelab を実施するための環境を整えましょう。

Google の権限の設定を確認する

この Codelab で構築するアクションをテストするには、必要な権限を有効にして、Actions Console のシミュレータがアクションにアクセスできるようにする必要があります。権限を有効にする手順は次のとおりです。

  1. [アクティビティ管理] ページに移動します。
  2. まだログインしていない場合は、Google アカウントにログインします。
  3. 次の権限を有効にします。
  • ウェブとアプリのアクティビティ
  • [ウェブとアプリのアクティビティ] の [Chrome の履歴と Google サービスを使用するサイト、アプリ、デバイスでのアクティビティを含める] チェックボックスをオンにします。

gactions コマンドライン インターフェースをインストールする

この Codelab では、「gactions コマンドライン インターフェース(CLI)ツール」を使用して、Actions Console とローカル ファイル システムの間で Actions プロジェクトを同期させます。

gactions CLI をインストールする手順については、gactions コマンドライン ツールをインストールするをご覧ください。

Firebase コマンドライン インターフェースをインストールする

Firebase コマンドライン インターフェース(CLI)を使用すると、Actions プロジェクトを Cloud Functions にデプロイしてウェブアプリをホストできます。

この Codelab では、npm を使用して Firebase CLI をインストールします。npm がインストールされていることを確認してください(通常は Node.js に付属しています)。

CLI をインストールまたはアップグレードするには、ターミナルを開いて次の npm コマンドを実行します。

npm install -g firebase-tools

CLI が正しくインストールされたことを確認するため、次のコマンドを実行します。

firebase --version

Firebase CLI のバージョンが 8 以降であることを確認します。これ以降のバージョンには、Cloud Functions に必要な最新の機能がすべて含まれています。バージョンが 8 以降でない場合は、npm install -g firebase-tools を実行してアップグレードしてください。

Firebase にログインするには、次のコマンドを実行します。

firebase login

Firebase にログインする際は、後で Actions プロジェクトの作成に使用する Google アカウントを使用してください。

リポジトリのクローンを作成する

このセクションでは、この Codelab に必要なファイルのクローンを作成します。これらのファイルを取得する手順は次のとおりです。

  1. ターミナルを開き、普段コーディング プロジェクトを保存しているディレクトリに移動します。そのようなディレクトリがない場合は、ホーム ディレクトリに移動します。
  2. このリポジトリのクローンを作成するには、ターミナルで次のコマンドを実行します。
git clone https://github.com/actions-on-google/actions-builder-canvas-codelab-nodejs

start/ ディレクトリを開きます。このリポジトリには、作業に使用する以下の重要なディレクトリが含まれています。

  • public/ - このディレクトリには、ウェブアプリの HTML、CSS、JavaScript のコードが格納されています。
  • sdk/custom/ - このディレクトリには、会話型アクション(シーン、インテント、型)のロジックが格納されています。
  • sdk/webhooks/ - このディレクトリは Webhook で、ゲームロジックが格納されています。

4864e8047bb2c8f6.png

図 3. start ディレクトリ コードの構造。

このセクションでは、Actions プロジェクトを作成して設定し、gactions CLI を使用してリポジトリのクローンからコードをプッシュし、ウェブアプリと Webhook をデプロイします。

Actions プロジェクトを作成する

Actions プロジェクトは、アクションのコンテナの役割を果たします。この Codelab の Actions プロジェクトを作成する手順は次のとおりです。

  1. Actions Console を開きます。
  2. [New project](新しいプロジェクト)をクリックします。
  3. [Project Name](プロジェクト名)に名前(たとえば canvas-codelab)を入力しますこの名前は内部参照用です。後でプロジェクトの表示名を設定することもできます。

7ea69f1990c14ed1.png

  1. [Create project](プロジェクトを作成)をクリックします。
  2. [What kind of Action do you want to build?](アクションの種類を選んでください)画面で [Game](ゲーム)カードを選択します。
  3. [Next](次へ)をクリックします。
  4. [Blank project](空のプロジェクト)カードを選択し、[Start building](始める)をクリックします。

アクションのプロジェクト ID を保存する

プロジェクト ID は、アクションの一意の識別子です。この Codelab では、いくつかの場面においてプロジェクト ID が必要になります。

プロジェクト ID を取得する手順は次のとおりです。

  1. Actions Console で、右上にあるその他アイコン(3 つの点のアイコン)をクリックします。
  2. [Project Settings](プロジェクトの設定)をクリックします。

6f59050b85943073.png

  1. [Project ID](プロジェクト ID)をコピーします。

請求先アカウントを関連付ける

この Codelab で Cloud Functions を使用してフルフィルメントをデプロイするには、請求先アカウントを Google Cloud のプロジェクトに関連付けておく必要があります。請求先アカウントがすでに関連付けられている場合、この手順はスキップしてかまいません。

請求先アカウントをプロジェクトに関連付ける手順は次のとおりです。

  1. Google Cloud Platform の [お支払い] ページに移動します。
  2. [請求先アカウントを追加] をクリックします。
  3. お支払い情報を入力し、[無料トライアルを開始] または [送信して課金を有効にする] をクリックします。
  4. ページの上部にある [マイ プロジェクト] タブをクリックします。
  5. Codelab の Actions プロジェクトの [アクション] の下にあるその他アイコンをクリックします。
  6. [お支払い情報を変更] をクリックします。
  7. プルダウン メニューで、設定した請求先アカウントを選択します。[アカウントを設定] をクリックします。

料金が発生しないようにするには、この Codelab の最後にある「次のステップ」ページの「プロジェクトをクリーンアップする」の手順に沿って、使用する予定のないプロジェクトを削除してください。

ウェブアプリをデプロイする

このセクションでは、Firebase CLI を使用してウェブアプリ(Snow Pal ゲーム)をデプロイします。デプロイが完了したら、ウェブアプリの URL を取得して、ブラウザでゲームがどのように表示されるかを確認できます。

ウェブアプリをデプロイする手順は次のとおりです。

  1. ターミナルで、start/ ディレクトリに移動します。
  2. 次のコマンドを実行します。{PROJECT_ID} はプロジェクト ID で置き換えます。
firebase deploy --project {PROJECT_ID} --only hosting

数分後、「Deploy complete!」(デプロイが完了しました)と表示されます。これは Snow Pal ウェブアプリが Firebase に正常にデプロイされたことを示します。

Snow Pal ゲームをブラウザで表示する手順は次のとおりです。

  1. ターミナルの出力から Hosting URL を取得します。URL は、https://{PROJECT_ID}.web.app のような形式になっています。
  1. ブラウザに URL を貼り付けます。Snow Pal ゲームの開始画面と Start Game ボタンが表示されます。

68429faae5141ed0.png

ウェブアプリの URL とプロジェクト ID を Actions プロジェクトに追加する

次に、ウェブアプリの URL とプロジェクト ID を actions.intent.MAIN.yaml ファイルに追加します。ウェブアプリの URL を追加することで、会話型アクションがどの URL にデータを送信すべきかを認識できるようになります。また、settings.yaml にプロジェクト ID を追加することで、ダウンロードしたファイルを Actions Console の適切なプロジェクトにプッシュできるようになります。

ウェブアプリの URL とプロジェクト ID を追加する手順は次のとおりです。

  1. テキスト エディタで start/sdk/custom/global/actions.intent.MAIN.yaml ファイルを開きます。
  2. url フィールドで、プレースホルダ文字列をウェブアプリの URL で置き換えます。
  3. テキスト エディタで start/sdk/settings/settings.yaml ファイルを開きます。
  4. projectId フィールドで、プレースホルダ文字列をプロジェクト ID で置き換えます。

プロジェクトを Actions Console にプッシュする

Actions Console をローカル プロジェクトで更新するには、Actions プロジェクトを Actions Console にプッシュする必要があります。手順は次のとおりです。

  1. sdk ディレクトリに移動します。
cd sdk/
  1. 次のコマンドを実行して、ローカル ファイル システムの設定を Actions Console にコピーします。
gactions push

Webhook をデプロイする

gactions push を実行したことで、Webhook の初期コードが Actions Console にインポートされています。Codelab では、この Webhook コードを Actions Console 内で編集していくことになります。ここでは、Actions Console から Webhook をデプロイします。

Webhook をデプロイする手順は次のとおりです。

  1. Actions Console で、上部のナビゲーション バーの [Develop](開発)をクリックします。
  2. 左側のナビゲーションで [Webhook] をクリックします。
  3. [Deploy Fulfillment](フルフィルメントをデプロイ)をクリックします。

Cloud Functions がフルフィルメントをプロビジョニングしてデプロイするまで数分かかる場合があります。コードエディタの上に「Cloud Function deployment in progress」(Cloud Functions のデプロイ中です)というメッセージが表示されます。コードが正常にデプロイされると、「Your Cloud Function deployment is up to date」(Cloud Functions のデプロイは最新です)というメッセージに変わります。

シミュレータでテストする

ここまでの変更により、アクションをウェブアプリにリンクすることができました。Actions Console シミュレータを使用すると、アクションを呼び出したときにウェブアプリが表示されるかどうかを確認できます。

次の手順でアクションをテストしてみましょう。

  1. Actions Console で、上部のナビゲーション バーの [Test](テスト)をクリックします。
  2. 入力欄に「Talk to Snow Pal sample」と入力し、Enter キーを押します。
  3. 入力欄に「Yes」と入力し、Enter キーを押します。または、画面中央の [Start Game](ゲームを開始)ボタンをクリックします。

37f7bc4e550d817c.png

文字や単語の推測を行うロジックがまだ設定されていないため、単語または文字を推測しても「...Incorrect. Keep on trying! It looks like we need to add more functionality to have this work properly.」(不正解です。諦めずに頑張りましょう!正しく動作させるにはさらに機能を追加する必要があるようです)という応答が返されます。

このプロジェクトの機能は、会話型アクション、ウェブアプリ、Webhook という 3 つの主要コンポーネントで構成されています。なお、これはあくまでもアクションの設定の一例で、Interactive Canvas の基本機能をわかりやすく説明するために構成したものです。

以降のセクションでは、会話型アクション、Webhook、ウェブアプリがどのように連携するかについて説明し、Interactive Canvas のその他の重要な要素について解説します。

会話型アクション

会話型アクション コンポーネントは、ユーザーからの入力を認識して処理し、適切なシーンに送信してユーザーへの応答を作成します。たとえば、Snow Pal ゲームでユーザーが「I guess the letter e」と言うと、会話型アクションはその文字をインテント パラメータとして抽出し、適切なゲームロジックに渡します。ゲームロジックは、ユーザーが指定した文字が正解かどうかを判定し、結果に応じてウェブアプリを更新します。この会話ロジックは、Actions Console のウェブベース IDE である Actions Builder を使って表示、変更できます。次のスクリーンショットに、Actions Builder で可視化した会話型アクションの一部を示します。

91d1c5300f015ff9.png

図 4. Actions Builder で可視化した Main invocation

このスクリーンショットに示されている Main invocation は、ユーザーが「Okay Google, talk to Snow Pal sample」(Okay Google, Snow Pal のサンプルにつないで)のように言うとインテントに一致します。ユーザーがアクションを呼び出すと、Main invocation から canvas レスポンスを含むプロンプトが送信されます。このレスポンスには、ウェブアプリの URL が含まれています。

アクションの最初の canvas レスポンスには、ウェブアプリの URL を含める必要があります。このレスポンスは、そのアドレスのウェブアプリをユーザーのデバイスにレンダリングするよう、アシスタントに伝える役割を果たします。Actions Builder で設定する追加の canvas レスポンスには、true に設定した send_state_data_to_canvas_app フィールドを含めることができます。このフィールドは、インテントが一致したときにインテント名とすべてのパラメータ値をウェブアプリに送信し、ユーザー入力から収集したデータに基づいてウェブアプリを更新します。

Webhook

この Codelab では、Webhook にゲームロジックが含まれています(ここでの Webhook は、ゲームサーバーの役割を果たすものと考えることができます)。このゲーム ロジックには、ユーザーの推測が正しいかどうか、ユーザーが勝ったか負けたかを判定し、結果に基づいて応答を作成するための要素が含まれています。Webhook は Actions Builder で編集できます。

アクションがゲームロジックを実行する必要がある場合は、Actions Builder が Webhook を呼び出します。たとえば、Game シーンの guess インテントは、guess ハンドラに対して Webhook 呼び出しを行い、ユーザーの推測が正しいかどうかを判定するためのロジックを実行します。Webhook は、ウェブアプリ ファイルにマッピングされたハンドラ内に Canvas レスポンスを含めることで、ウェブを適切に更新することができます。

ウェブアプリ

ca564ef59e1003d4.png

図 5. Interactive Canvas アクションの会話型アクション、Webhook、ウェブアプリ間のやり取りを視覚的に表現した図。

ウェブアプリ ファイルには、ウェブアプリの映像とアニメーションのコードと、ユーザー入力に基づいてウェブアプリを更新するためのロジックが含まれています。ウェブアプリ ファイルはテキスト エディタで編集でき、変更は Firebase CLI を使用してデプロイできます。

会話型アクションとウェブアプリの間の通信

ユーザーの入力に基づいてウェブアプリを更新するには、会話型アクションとウェブアプリの間の通信を有効にする必要があります。たとえば、ユーザーが「I guess the letter f」と言った場合、

会話型アクションからウェブアプリに文字が「f」であることを伝え、それに応じてウェブアプリが更新されるようにする必要があります。ユーザー入力を会話型アクションからウェブアプリに渡すには、Interactive Canvas API で読み込む必要があります。

この API のスクリプトは、Snow Pal ゲームのメインの HTML ファイル /public/index.html に含まれています。このファイルが UI の外観を定義し、いくつかのスクリプトを読み込みます。

index.html

<!-- Load Assistant Interactive Canvas API -->
 <script type="text/javascript" src="https://www.gstatic.com/assistant/interactivecanvas/api/interactive_canvas.min.js"></script>

ユーザー入力に基づいてウェブアプリを更新するには、ウェブアプリ ファイルでコールバックを登録して設定する必要もあります。コールバックを使用すると、会話型アクションからの情報やリクエストにウェブアプリから応答できます。

/public/js/action.js には、コールバックを宣言して登録するための事前設定クラス Action があります。Action クラスは Interactive Canvas API のラッパーです。次のスニペットに示すように、scene.jscreate() 関数でウェブアプリを作成すると、新しい Action インスタンスが作成されてsetCallbacks() が呼び出されます。

scene.js

// Set assistant at game level.
this.assistant = new Action(this);
// Call setCallbacks to register assistant action callbacks.
this.assistant.setCallbacks();

setCallbacks() 関数は、/public/js/action.jsAction クラスで定義されています。この関数は、ゲーム作成時にコールバックを宣言して Interactive Canvas API に登録します。

  setCallbacks() {
    // Declare the Interactive Canvas action callbacks.
    const callbacks = {
      onUpdate: (data) => {
     ...
    // Called by the Interactive Canvas web app once web app has loaded to
    // register callbacks.
    this.canvas.ready(callbacks);
  }

setCallbacks() 関数が宣言する onUpdate() コールバックは、Canvas レスポンスを送信するたびに呼び出されます。

次のセクションでは、このプロジェクトの特定のコードを設定し、Conversational Action からウェブアプリにデータを渡す方法について説明します。

ユーザー入力に基づいてウェブアプリを更新する

この Codelab では、コマンドマップを使用し、ユーザーの入力に基づいてウェブアプリを更新します。たとえば、Welcome シーンで start_game インテントが一致すると、プロンプトに含まれる canvas レスポンスがウェブアプリに送信されます。onUpdate() は、canvas レスポンスからのメタデータを解析して START_GAME コマンドを呼び出します。これにより、scene.jsstart() 関数が呼び出され、ウェブアプリが更新されて新しいゲームが始まります。

scene.jsstart() 関数は、updateCanvasState() 関数も呼び出します。この関数は、setCanvasState() というメソッドを使用して、Webhook からアクセス可能な状態データを追加します。

この Codelab でもさまざまなコマンドを追加しますが、こうしたすべてのコマンドの最後に呼び出されてウェブアプリの状態を更新するのが updateCanvasState() メソッドです。updateCanvasState() が呼び出されるたびに、displayedWordincorrectGuesses の値が現在の状態に基づいて更新されます。

scene.js

...
  updateCanvasState() {
    window.interactiveCanvas.setCanvasState({
      correctWord: this.word.text,
      displayedWord: this.word.displayText.text,
      incorrectGuesses: this.incorrectGuesses,
    });

更新後の状態は、次の会話ターンで使用できます。次のコード スニペットに示すように、Webhook 内のこの状態には conv.context.canvas.state でアクセスできます。

index.js

...
  let displayedWord = conv.context.canvas.state.displayedWord;
...

このセクションでは、アクションに guess 機能を追加して、ユーザーが単語内の文字または単語自体を推測できるようにします。

会話型アクション

「シミュレータでテストする」セクションで返された応答には、「It looks like we need to add more functionality to have this work properly.」(正しく動作させるにはさらに機能を追加する必要があるようです)とありました。ここでは、Actions Console でそのプロンプトを削除して、Webhook の呼び出しのみが発生するようにします(すでに Game シーンは、guess インテントが一致したら Webhook 呼び出しを実行するように設定されています)。

guess インテントが一致したときの静的プロンプトを削除する手順は次のとおりです。

  1. Actions Console で、左側のナビゲーションの [Scenes](シーン)をクリックします。
  2. [Game] をクリックして Game シーンに移動します。
  3. [Custom intent handling](カスタム インテントの処理)の [When guess is matched](推測が一致したとき)をクリックし、[Send prompts](プロンプトを送信)をオフにしてプロンプトを削除します。
  4. [Save](保存)をクリックします。

Webhook

このセクションでは、Webhook のロジックに変更を加え、ユーザーの推測の正誤をウェブアプリ ファイルのロジックにマッピングすることで、正誤に応じてウェブアプリが更新されるようにします。guess インテント ハンドラはあらかじめ Webhook に設定されているため、このインテントに Canvas レスポンスを追加するだけで、ウェブアプリを更新するロジックをトリガーできます。

Webhook を変更する手順は次のとおりです。

  1. Actions Console で、左側のナビゲーションの [Webhook] をクリックします。
  2. 次のコードを、index.jsguess ハンドラの下に追加します。

index.js(セクション A):

// Add SECTION A `conv.add(new Canvas({` content here
conv.add(new Canvas({
  data: {
    command: 'CORRECT_ANSWER',
    displayedWord: displayedWord
  },
}));

index.js(セクション B):

// Add SECTION B `conv.add(new Canvas({` content here
conv.add(new Canvas({
  data: {
    command: 'INCORRECT_ANSWER',
  },
}));
  1. [Save Fulfillment](フルフィルメントを保存)をクリックします。
  2. [Deploy Fulfillment] をクリックします。デプロイが完了すると、エディタの上に「Your Cloud Function deployment is up to date」というメッセージが表示されます。

ウェブアプリ

ウェブアプリで CORRECT_ANSWER コマンドと INCORRECT_ANSWER コマンドを処理できるように設定する手順は次のとおりです。

  1. テキスト エディタで public/js/action.js を開きます。
  2. ウェブアプリを次のように変更し、CORRECT_ANSWER コマンドと INCORRECT_ANSWER コマンドを処理できるようにします。

action.js(セクション C):

// Add SECTION C `CORRECT_ANSWER: (params) => {` content here
      CORRECT_ANSWER: (params) => {
        this.gameScene.correctAnswer(params);
      },
      INCORRECT_ANSWER: (params) => {
        this.gameScene.incorrectAnswer();
      },
  1. 次のコマンドを実行してウェブアプリを更新します。
firebase deploy --project {PROJECT_ID} --only hosting

シミュレータでアクションをテストする

ここまでの変更により、ユーザーの推測の正誤を判定し、それに応じてウェブアプリを更新できるようになりました。

次の手順でアクションをテストしてみましょう。

  1. ナビゲーション バーで、[Test] をクリックします。
  2. 入力欄に「Talk to Snow Pal sample」と入力し、Enter キーを押します。
  3. 入力欄に「Yes」と入力し、Enter キーを押します。または、候補ワードの [はい] ボタンをクリックします。
  4. 推測する文字を入力し、Enter キーを押します。

1c2c2d59a418642b.png

コードを理解する

前のセクションでは、ゲーム内でユーザーが文字を推測できるようにし、その推測が正しければ単語に、間違っていれば Snow Pal に反映するコードを追加しました。大まかな流れとしては、guess インテントが一致すると Actions Builder で Webhook 呼び出しが発生し、渡されるデータに応じてウェブアプリが更新されます。たとえば、ユーザーが推測した文字が単語に含まれている場合は、ウェブアプリが更新されてその文字が単語内の正しい位置に表示されます。

Interactive Canvas を使用するアクションの場合、通常は次のような流れで Webhook からウェブアプリにデータが渡されます。

  1. ユーザーからの入力が、Canvas レスポンスを含むインテントに一致します。
  2. 会話型アクションまたは Webhook が Canvas レスポンスを送信します。これにより、onUpdate() コールバックがトリガーされます。
  3. onUpdate() コールバックが、ウェブアプリを更新するカスタム ロジックにマッピングされます。

このプロジェクトのコードは次のように動作します。

  1. ユーザーが guess インテントに一致すると、Actions Builder がユーザー入力から文字をパラメータとして抽出します。
  2. Actions Builder が、Webhook の guess ハンドラを呼び出します。このハンドラには、ユーザーが推測した文字が単語に含まれているかどうかを判定するロジックが含まれています。
  3. guess ハンドラには、文字が正しかった場合と間違っていた場合に実行される 2 つの Canvas レスポンスが含まれています。それぞれの Canvas レスポンスは、該当するデータ(CORRECT_ANSWER または INCORRECT_ANSWER コマンド)をウェブアプリに渡します。
  4. Canvas レスポンスの data フィールドに含まれるデータは、action.jsonUpdate() メソッドに渡されます。onUpdate() は、scene.js のコマンド マップ内の適切なコマンドを呼び出します。
  5. コマンドマップは、scene.jscorrectAnswer() 関数と incorrectAnswer() 関数にマッピングされています。これらの関数がユーザーの推測に基づいてウェブアプリを更新し、ウェブアプリから Webhook に状態データを送信する setCanvasState() を呼び出します。

このセクションでは、ゲームの勝敗機能をアクションに追加します。この機能には、ユーザーが勝ったか負けたかを判定するロジックと、結果に基づいてウェブアプリの画像を更新するロジックが含まれています。

会話型アクション

ユーザーの勝敗を処理する機能は guess インテント内で設定するため、Actions Builder での追加設定は必要ありません。

Webhook

このセクションでは、ユーザーの勝敗を処理するロジックを Webhook に追加し、適切な勝敗画面でゲームを更新するウェブアプリ ロジックにマッピングします。

Webhook を変更する手順は次のとおりです。

  1. Actions Console で、左側のナビゲーションの [Webhook] をクリックします。
  2. 次のコードを、index.jsguess ハンドラの下に追加します。

index.js(セクション D):

// Add SECTION D `if (userHasWon)` content here
    if (userHasWon) {
      conv.add(`<speak>Let's see if your guess is there...<break
        time='2500ms'/> ${guess} is right. That spells ${correctWord}!
        ${randomArrayItem(WIN_RESPONSES)}</speak>`);
      conv.add(new Canvas({
        data: {
          command: 'WIN_GAME',
          displayedWord: displayedWord
        },
      }));
      conv.add(`<speak>${PLAY_AGAIN_INSTRUCTIONS}</speak>`);
    } else {

index.js(セクション E):

// Add SECTION E `}` here
}

index.js(セクション F):

// Add SECTION F `Check if the user has exceeded the maximum` content here
// Check if the user has exceeded the maximum amount of max guesses allowed.
    const userHasLost = conv.context.canvas.state.incorrectGuesses + 1 >= MAX_INCORRECT_GUESSES;
    if (userHasLost) {
      conv.add(`<speak>Let's see if your guess is there...<break
      time='2500ms'/> ${guess} is wrong. Sorry you lost. The word is ${correctWord}!</speak>`);
      conv.add(new Canvas({
        data: {
          command: 'LOSE_GAME',
        },
      }));
      conv.add(`<speak>${PLAY_AGAIN_INSTRUCTIONS}</speak>`);
    } else {

index.js(セクション G):

// Add SECTION G `}` here
}
  1. [Save Fulfillment] をクリックします。
  2. [Deploy Fulfillment] をクリックします。デプロイが完了すると、エディタの上に「Your Cloud Function deployment is up to date」というメッセージが表示されます。

これで、2 つの Canvas レスポンスを WIN_GAME コマンドと LOSE_GAME コマンドに追加し、ユーザーがゲームに勝ったときと負けたときに対応できるようになりました。次のセクションでは、ユーザーの勝敗に基づいてウェブアプリを更新する機能を追加します。

ウェブアプリ

ここでは、ユーザーが勝ったか負けたかに応じてウェブアプリが更新されるように設定します。ウェブアプリを更新する手順は次のとおりです。

  1. テキスト エディタで public/js/action.js を開きます。
  2. ウェブアプリを次のように変更し、WIN_GAME コマンドと LOSE_GAME コマンドを処理できるようにします。

action.js(セクション H):

// Add SECTION H `WIN_GAME: (params) => {` content here
      WIN_GAME: (params) => {
        this.gameScene.winGame(params);
      },
      LOSE_GAME: (params) => {
        this.gameScene.loseGame();
      },
  1. 次のコマンドを実行してウェブアプリを更新します。
firebase deploy --project {PROJECT_ID} --only hosting

シミュレータでアクションをテストする

ここまでの変更により、ユーザーがゲームに勝ったか負けたかに応じて、適切な画面を表示できるようになりました。

次の手順でアクションをテストしてみましょう。

  1. Actions Console で、上部のナビゲーション バーの [Test] をクリックします。
  2. 入力欄に「Talk to Snow Pal sample」と入力し、Enter キーを押します。
  3. 入力欄に「Yes」と入力し、Enter キーを押します。または、画面中央の [Start Game] ボタンをクリックします。
  4. 勝敗が決まるまで文字や単語を推測します。

ee572870f9a7df36.png

もう一度プレイしようとすると、必要な機能がまだ追加されていないことを示すメッセージが表示されます。この機能は次のセクションで追加します。

コードを理解する

勝敗機能の仕組みは推測機能と同じです。ユーザーが guess インテントに一致すると、Webhook がユーザーの推測を評価します。ユーザーの推測が正しいときは、ユーザーが勝ったかどうかをチェックし、すでに勝っていた場合はウェブアプリに WIN_GAME コマンドを送信します。推測が間違っていたときは、ユーザーが負けたかどうかをチェックし、負けていた場合はウェブアプリに LOSE_GAME コマンドを送信します。これらのコマンドにより、scene.jswinGame() 関数または loseGame() 関数がトリガーされ、ウェブアプリが勝利画面または敗北画面を表示してゲームの状態を更新します。

このセクションでは、ユーザーが「Play Again」(もう一度プレイする)と話しかけるか、ウェブアプリで [Play Again] ボタンをクリックして新しいゲームを開始できるようにする機能を追加します。Actions Builder で play_again インテントに変更を加えて、ウェブアプリを適切に更新する canvas レスポンスが送信されるようにし、ユーザーが Play Again ボタンをクリックしたときに play_again インテントをトリガーするロジックを追加します。

会話型アクション

前のセクションでアクションをテストしたときに、ゲームをもう一度プレイしようとすると、「That would be great, but we will build this functionality in a later section. For now, just reset the Action.」(ありがとうございます。しかしながら、この機能は後のセクションで構築することになっています。今回はアクションをリセットしてください)というプロンプトが返されました。ここではこのプロンプトを削除し、ユーザーがもう一度プレイすることをリクエストした場合の応答プロンプト(「Okay, here's another game!」(では、新しいゲームを開始します!))で置き換えて、ウェブアプリをトリガーしてゲームをもう一度開始するための canvas レスポンスを追加します。

ユーザーがもう一度プレイすることを選択した場合のプロンプトを変更する手順は次のとおりです。

  1. Actions Console で、[Scene] プルダウンをクリックします。
  2. Game シーンをクリックします。
  3. [Custom intent handling] で When play_again is matched をクリックします。
  4. 次のようにプロンプトを置き換えます。
candidates:
  - first_simple:
      variants:
        - speech: 'Okay, here's another game!'
    canvas:
      sendStateDataToCanvasApp: true
  1. [Save] をクリックします。

Webhook

この Codelab では、Webhook でゲームロジックを管理しています。「Play again」機能はロジックの検証が必要ないため、Webhook を呼び出す必要はありません。代わりに、canvas レスポンスを Actions Builder から直接送信し、ウェブアプリに必要なデータ(前のセクションで設定したデータ)を渡すことができます。

ウェブアプリ

ここでは、ウェブアプリのファイルに変更を加え、ユーザーがもう一度プレイすることを選択した場合に適切に更新されるようにします。この機能を追加する手順は次のとおりです。

  1. テキスト エディタで public/js/action.js を開きます。
  2. ウェブアプリを次のように変更し、PLAY_AGAIN コマンドを処理できるようにします。

action.js(セクション I):

// Add SECTION I `PLAY_AGAIN: (params) => {` content here
      PLAY_AGAIN: (params) => {
        this.gameScene.start();
      },
  1. テキスト エディタで public/js/scene.js を開きます。
  2. ウェブアプリを更新して、ユーザーが [Play Again] ボタンをクリックすると新しいゲーム セッションが開始するようにします。

scene.js(セクション J)

// Add SECTION J `sendTextQuery` content here
     window.interactiveCanvas.sendTextQuery('Play again');
  1. 次のコマンドを実行してウェブアプリを更新します。
firebase deploy --project {PROJECT_ID} --only hosting

シミュレータでアクションをテストする

ここまでの変更により、ユーザーが「Play again」と言うか [Play again] ボタンを押すと、新しいゲーム セッションを開始できるようになりました。

次の手順でアクションをテストしてみましょう。

  1. ナビゲーション バーで、[Test] をクリックします。
  2. 入力欄に「Talk to Snow Pal sample」と入力し、Enter キーを押します。
  3. 入力欄に「Yes」と入力し、Enter キーを押します。または、画面中央の [Start Game] ボタンをクリックします。
  4. 勝敗が決まるまで文字や単語を推測します。
  5. 入力欄に「Play Again」と入力し、Enter キーを押します。または、候補ワードの [Play Again] をクリックします。

1fbc7193f7a9d0f5.png

コードを理解する

アクションのテストで、音声入力(「Play again」)またはクリック入力([Play again] ボタン)で新しいゲームが始まることを確認できました。

音声入力の場合は、ユーザーが「Play again」またはそれに似たフレーズを言うと、play_again インテントに一致してプロンプト(「Okay, here's another game!」)がプロンプト キューに追加されます。プロンプトに含まれている canvas レスポンスは、インテント名などのメタデータをウェブアプリに送信します。このインテント名が onUpdate() コールバックに渡され、対応するコマンド PLAY_AGAINaction.js のコマンドマップにマッピングされます。最後に PLAY_AGAIN コマンドにより scene.jsstart() 関数がトリガーされ、ウェブアプリが新しいゲーム セッションで更新されます。

クリック入力の場合は、Interactive Canvas API の sendTextQuery(), を使用して、ユーザーがボタンをクリックするとインテントがトリガーされるようにします。

この Codelab では、ユーザーが [Play Again] ボタンをクリックしたときに、sendTextQuery() を使用して play_again インテントを呼び出します。Play again 引数が play_again インテントのトレーニング フレーズと一致すると、ユーザーが「Play Again」と言った場合と同じ方法でこのインテントがトリガーされます。最後に、play_again インテントによりロジックがトリガーされ、ウェブアプリが更新されて新しいゲーム セッションが始まります。

このセクションでは、PLAY_GAME という暗黙的呼び出しに変更を加えます。

暗黙的呼び出し PLAY_GAME を使用すると、「ゲームで遊ぶ」のような一般的なリクエストでこのアクションを呼び出せるようにすることができます。

ソースコードの PLAY_GAME グローバル インテントは、/sdk/custom/global/actions.intent.PLAY_GAME.yaml に含まれています。Actions Console では、次のスクリーンショットのように [Invocation](呼び出し)の下に [PLAY_GAME] として表示されます。

b4a73c0ddd88f6d5.png

ユーザーがこの暗黙的呼び出しを介してアクションを呼び出せるようにするには、ウェブアプリの URL を含む canvas レスポンスを、暗黙的呼び出し PLAY_GAME に追加する必要があります。手順は次のとおりです。

  1. Actions Console で、左側のナビゲーションの [PLAY_GAME] をクリックします。
  2. 次のスニペットのように、プロンプトを変更してウェブアプリの URL を追加します。
candidates:
  - canvas:
      url: 'https://<PROJECT_ID>.web.app'
  1. [Save] をクリックします。

シミュレータでアクションをテストする

ここまでの変更により、アクションが暗黙的呼び出し PLAY_GAME に対応できるようになりました。

次の手順でアクションをテストしてみましょう。

  1. ナビゲーション バーで、[Test] をクリックします。
  2. [Test fulfillment for system intents](システム インテントのフルフィルメントのテスト)をクリックします。
  3. [Invoke Action](アクションを呼び出す)をクリックします。

1a4f647e17ebab53.png

シミュレータでアクションが呼び出されます。

このセクションでは、正しく動作しない Interactive Canvas アクションをデバッグする方法について説明します。Snow Pal プロジェクトには、デバッグ オーバーレイがあらかじめパッケージ化されています。これを有効にすることで、次のスクリーンショットのように、画面の右下に console.log()console.error() の出力がすべて表示されるようになります。

4c8531d24366b5df.png

このオーバーレイを有効にするには、/public/css/main.css ファイルを開き、次のスニペットのように display: none !important; の行をコメント化します。

main.css

.debug {
 display: flex;
 flex-direction: column;

/* Comment below to view debug overlay */
/* display: none !important; */

 width: 500px;
 height: 150px;
 right: 0;
 bottom: 0;
 position: absolute;
}

これで完了です。

これで Interactive Canvas の Codelab 入門編は完了です。独自の Interactive Canvas アクションを作成するために必要なスキルを身に付けることができました。

学習した内容

  • Interactive Canvas アクションを構築、デプロイ、テストする方法
  • Canvas レスポンスを使用してウェブアプリを更新する方法
  • sendTextQuery()setCanvasState() などを使用してアクションを拡張する方法
  • アクションをデバッグする方法

その他の学習リソース

Interactive Canvas の詳細について詳しくは、以下のリソースをご覧ください。

プロジェクトをクリーンアップする(推奨)

料金が発生するのを避けるため、使用する予定のないプロジェクトは削除することをおすすめします。この Codelab で作成したプロジェクトを削除する手順は次のとおりです。

  1. Cloud プロジェクトとリソースを削除する手順については、プロジェクトのシャットダウン(削除)をご覧ください。
  1. 省略可: プロジェクトを Actions Console からすぐに削除したい場合は、プロジェクトを削除する手順を完了してください。この手順で削除していないプロジェクトは、約 30 日後に自動的に削除されます。

アンケート

最後に、簡単なアンケートにご協力ください。