Skill Flow Builderの基本構文

Skill Flow Builderの基本構文

Skill Flow Builderには、ゲームやストーリー向けに次のようなメタデータ形式が用意されています。コンテンツの形式設定について詳しくは、Skill Flow Builderのリファレンスを参照してください。

シーンのプロパティ

Skill Flow Builderでは、シーンが基本要素です。シーンにはさまざまなタイプのコンテンツが含まれ、ストーリーやゲームの流れに応じてあらゆる方向につなげていくことができます。

以下は、あるシーンの構造を表しています。

@scene name
    *say
        コンテンツ
    *reprompt
        コンテンツ
    *show
        コンテンツ
    *then
        シーンの指示

シーン名でシーンを特定します。シーン名の形式は次のとおりです。

  • @で始める必要があります。
  • 英字、数字、スペースで構成し、文字数制限はありません。
  • ストーリー内で一意である必要があります。
  • シーン名は1行に収める必要があります。

一部のシーン名は特殊用途向けに予約されています。詳細については、特殊シーンを参照してください。

*say

シーンが再生されると、Alexaは*sayプロパティで定義したコンテンツをユーザーに読み上げます。*sayプロパティの形式は次のとおりです。

  • 任意です。
  • 複数行に記述できます
  • SSMLを使用できます。
  • バリエーションを示すために||を使用できます。
  • 波括弧を使って変数値を挿入できます。

||(ダイアログバリエーション)

    *say
        このようなものですか
        ||
        それともこのようなものですか

||は、ランダムに選択されるバリエーションを指定します。コンテンツの繰り返しによってストーリーが退屈にならないようにするのに効果的です。ダイアログバリエーションは、*say*reprompt*recapで使用できます。

*reprompt

Alexaは、ゲームでプレイヤーが答えるべきときに何も言わない場合、*repromptプロパティのコンテンツを声に出して読み上げます。*repromptを指定しなかった場合、Alexaはデフォルトで直前のシーンに指定した*sayコンテンツを再度読み上げます。

*sayと同様に、*repromptプロパティにも次のような形式が定められています。

  • 任意です。
  • 複数行に記述できます
  • SSMLを使用できます。
  • バリエーションを示すために||を使用できます。
  • 波括弧を使って変数値を挿入できます。

*recap

Alexaは、プレイヤーが想定外の応答をした場合、*recapプロパティのコンテンツを声に出して読み上げます。

*sayと同様に、*recapプロパティにも次のような形式が定められています。

  • 任意です。
  • 複数行に記述できます
  • SSMLを使用できます。
  • バリエーションを示すために||を使用できます。
  • 波括弧を使って変数値を挿入できます。

*show

プレイヤーが視覚を使用するコンテンツに対応するデバイスを使っている場合、デバイスはこのセクションに割り当てられた視覚コンポーネントを表示します。視覚要素を追加するを参照してください。

*then

*thenプロパティには、シーンの指示が入ります。シーンの指示とは、Alexaがそのシーンのコンテンツを再生した後に順次実行されるコマンドのことです。

シーンの指示

-> (遷移先のシーン)

Alexa Content Engineに、別のシーンに遷移するよう指定する終端子です。

    *then
        -> start

->指示の形式は次のとおりです。

  • 直後にシーン名を指定する必要があります。
  • 波括弧を使って変数を挿入できます。たとえば、twoという変数の値が2の場合、-> scene {two}@scene 2に遷移します。
  • 終端子のため、シーンの終わりを表します。終端子が実行されたらすぐに、処理は次のシーンに遷移します。

hear

hear指示は、Alexaが聞き取る単語やフレーズと、聞き取った後のアクションを指定します。

    *then
        hear 逃げて, ここから出て, 行って {
            decrease courage by 1
            -> run
        }
        hear 隠れて {
            set fear to 10
            -> hide
        }

hear指示の形式は次のとおりです。

  • カンマで区切って複数のフレーズを指定できます。
  • 波括弧で囲む必要があります。
  • if文の中でも使用できます。また、if文を含めることもできます。

プレイヤーの名前、またはAlexaのスロット値をたずねる

正確なフレーズや単語を待機するには、hear指示を使ってそれらのフレーズや単語を記述します。プレイヤーに選択肢を与えるセクションを参照してください。

プレイヤーが何を言うかを予測できなかったり、考えられる組み合わせをすべて書き出すことができないケースも考えられます。たとえば、プレイヤーの名前を知りたい場合、考えられるすべての名前を書き出すことは非現実的です。

以下は、「お名前を教えてください」とたずねる@ask player nameというシーンの例です。

@ask player name
    *say
        お名前を教えてください。
    *then
        slot playerName to 'AMAZON.FirstName'
        hear {playerName}, 私の名前は{playerName}です {
            -> next scene
        }
@next scene
    *say
        こんにちは、{playerName}さん

構造は、プレイヤーに選択肢を与えるで使ったhearコマンドに似ていますが、次のような違いがあります。

  • slot playerName to 'AMAZON.FirstName'

    slot指示はAlexaに、hearコマンドで{playerName}を使用している場合には、日本の下の名前を待機する必要があると指示しています。詳細については、ビルトインインテントとスロット値を参照してください。

  • hear {playerName}, 私の名前は{playerName}です {

    この指示はAlexaに、{playerName}そのもの、または「私の名前は」と「です」にはさまれた{playerName}を待機するよう指示しています。たとえば、プレイヤーが「私の名前はハルキです」と答えた場合、playerNameの値は「ハルキ」となります。

  • こんにちは、{playerName}さん

    保存した値をコンテンツに挿入するには波括弧を使います。たとえば、プレイヤーが@ask player nameシーン内で「私の名前はハルキです」と言った場合、プレイヤーは@next sceneから「こんにちは、ハルキさん」と聞くことになります。

よく使う別のスロットタイプに、AMAZON.NUMBERがあります。これは、プレイヤーに数字をたずねる場合に使用できます。

ビルトインスロットタイプの詳細については、スロットタイプリファレンスを参照してください。

シーンを作成する

プレイヤーが初めてゲームを起動するときは、スキルはプレイヤーに応答し、プロンプトを出す必要があります。startシーンを作成し、初回起動時の動作を定義してください。以下の例は、Alexaに「すごいゲームにようこそ!」と言うように指示するstartシーンを表しています。

@start
    *say
        すごいゲームにようこそ!

どのシーンも必ず、新しい行で先頭に@を付けたシーン名から始めます。この例のシーン名は、startです。startなど一部のシーン名は予約されており、特殊な動作にのみ使用されます。

シーンにコンテンツを追加するには、シーンのプロパティを使います。プロパティには、シーン内でAlexaが読み上げるコンテンツを指定する*sayなどがあります。シーンのプロパティは、新しい行で先頭に*を付けたプロパティ名で指定します。

    *say
        すごいゲームにようこそ!

この文、すごいゲームにようこそ!は、*sayプロパティのコンテンツです。コンテンツは、先頭に*を付けた別のプロパティか、@を付けた別のシーンが始まるまで、複数行にわたって続けられます。インデントは任意です。

プレイヤーに選択肢を与える

以下は、プレイヤーが海賊になるか商人になるかを選択できるstartシーンの例です。

@start
    *say
        すごいゲームにようこそ!
        海賊と商人、どちらになりたいですか?
    *then
        hear 海賊になりたい, 海賊, 海賊になる {
            -> choose pirate
        }

        hear 商人になりたい, 商人, 商人になる {
            -> choose merchant
        }

シーンでは、*sayプロパティを使ってAlexaに「すごいゲームにようこそ! 海賊と商人、どちらになりたいですか?」を言わせ、*thenプロパティを使って次の指示を列挙しています。

        hear 海賊になりたい, 海賊, 海賊になる {
            -> choose pirate
        }

hear指示は、Alexaが特定の単語やフレーズを聞き取ったら特定のアクションを取るように指示しています。同じ意味の単語やフレーズをカンマで区切って指定できます。

この例では、Alexaが「海賊になりたい」、「海賊」、「海賊になる」を待機しています。Alexaがプレイヤーからこれらのフレーズのいずれかを聞き取ると、Alexaは{}の間に指定された指示を実行します。

プレイヤーが「海賊」と言うと、Alexaは-> choose pirateを実行します。つまり、Alexaに「choose pirate」シーンに遷移するよう指示しています。->指示の遷移はすぐに行われますが、シーン内の残りの指示は実行されません。

複数のシーンをつなげる

プレイヤーからのインプットがなくても、シーン間の遷移を行う場合もあります。次の例を考えてみましょう。

バージョン1:

@start
    *say
        すごいゲームにようこそ!
        海賊と商人、
        どちらになりたいですか?
    *then
        hear 海賊 {
            -> choose pirate
        }
        hear 商人 {
            -> choose merchant
        }

バージョン2:

@start
    *say
        すごいゲームにようこそ!
    *then
        -> choose your trade

@choose your trade
    *say
        海賊と商人、
        どちらになりたいですか?
    *then
        hear 海賊 {
            -> choose pirate
        }
        hear 商人 {
            -> choose merchant
        }

プレイヤーにとって、これらの例の結果はまったく同じです。しかし、次の理由からバージョン2のほうがより便利です。

  • ゲームが進んだときに、「すごいゲームにようこそ!」と言わなくても直接@choose your tradeの質問に遷移できます。
  • プレイヤーが何も答えず、Alexaが質問を繰り返さなければならない場合、Alexaは最後のシーンの質問だけを言うことができます。

音響効果を追加する

AlexaでサポートされるSSMLタグを使ってコンテンツをカスタマイズできます。コンテンツに音響効果やオーディオファイルを追加するには、SSMLのaudioタグを使います。SSMLリファレンスのaudioタグを参照してください。

@start
    *say
        すごいゲームにようこそ!
        <audio src='https://s3.amazonaws.com/.../yourAudioFile.mp3' />
        海賊と商人、どちらになりたいですか?

別の音声を追加する

SSMLのvoiceタグを使って、Alexaスキルでさまざまな音声を使用できます。さまざまな音声の詳細については、SSMLリファレンスのvoiceタグを参照してください。

    @start
        *say
            <voice name='Kendra'>私は人間ではありません。</voice>

プレイヤーの決定、インベントリー、進行状況を保存する

後で使えるように、プレイヤーに関する情報を保存しておきたい場合があります。たとえば、次のような情報です。

  • プレイヤーがパリに行ったこと
  • プレイヤーが魔法使いに話しかけたこと
  • プレイヤーが魔法使いに「いいえ」と答えたこと
  • プレイヤーが何でも開けられる鍵を見つけたこと

以下は、flag指示を使って情報を保存する方法の例です。

*then
    flag visitedParis
    flag talked_to_wizard
    flag toldWizardNo

同様に、プレイヤーの選択内容に基づいてフラグをセットすることもできます。

*then
    hear 鍵を拾って {
        flag skeletonkey
        -> escape room
    }

プレイヤーが「鍵を拾って」と言うと、skeletonkeyというフラグがセットされ、ゲームはescape roomというシーンに進みます。

フラグを解除するには、unflag指示を使います。たとえば、プレイヤーがあるシーンで何でも開けられる鍵を失くすと、以下を実行します。

    *then
        unflag skeletonkey

保存したプレイヤーの決定、インベントリー、進行状況を使って何らかのアクションを実行する

プレイヤーに関する情報を保存したら、その情報を使って何らかのアクションを実行するかどうかを判断します。

たとえば、プレイヤーは何でも開けられる鍵を持っていないと扉を開けられないとします。

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if skeletonkey {
            -> open door
        }

        -> door locked

事前にskeletonkeyのフラグがセットされている場合、ゲームは自動でopen doorというシーンに進みます。事前にskeletonkeyのフラグが解除されているか、一度もセットされていない場合、ゲームは自動でdoor lockedというシーンに進みます。

if指示を使って、Alexaにif以降の文がtrueかfalseかをチェックするよう指示します。if文以降がtrueの場合(フラグがセットされているなど)、Alexaは{}の間に指定された指示を実行します。フラグが解除されている場合は、falseと解釈され、{}の間に書かれた指示は実行されません。

宣言されていないフラグはすべて、falseとみなされます。

以下は、「...でない」(!)記号をif文内で使用する方法の例です。これらの例は論理的には同じであり、プレイヤーのエクスペリエンスも同じになります。

バージョン1:

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if skeletonkey {
            -> open door
        }

        -> door locked

バージョン2:

@escape room
    *say
        あなたは今部屋の中にいます。
    *then
        if !skeletonkey {
            -> door locked
        }

        -> open door

以下は、if指示内に指定されたflagunflagなど、複数の指示を実行する方法の例です。これは、何でも開けられる鍵がゲーム内で1回しか使えないアイテムの場合に便利です。

*then
        if skeletonkey {
            unflag skeletonkey
            -> open door
        }

複数のフラグをチェックする

andorを使ってif文内の複数のフラグをチェックします。

*then
        if skeletonkey and talked_to_wizard {
            -> open door
        }

この例は、プレイヤーが何でも開けられる鍵を持っており、かつ魔法使いに話しかけた場合にのみ扉を開けられるという設定を表します。ここでは、フラグが2つともセットされなければ文がtrueにはなりません。

以下は、orを使った例です。

*then
        if skeletonkey or talked_to_wizard {
            -> open door
        }

こちらは、プレイヤーが何でも開けられる鍵を持っているか、魔法使いに話しかけたかのいずれかの場合に扉を開けられるという設定を表します。

変数を設定し使用する

ゲームがプレイされなければ判断できない値を処理するには、変数を使います。たとえば、playerClassという変数を作成して、ゲーム中にプレイヤーが選択するキャラクターのクラスを格納します。

以下は、プレイヤーの応答に基づいてクラスを設定する方法の例です。

@choose class
    *say
        クラスを選んでください。戦士、賢者、盗賊の
        どれですか?
    *then
        hear 戦士 {
            set playerClass as '戦士'
            -> play introduction
        }

        hear 賢者 {
            set playerClass as '賢者'
            -> play introduction
        }

        hear 盗賊 {
            set playerClass as '盗賊'
            -> play introduction
        }

シーンの*thenセクションで、Alexaはプレイヤーが「戦士」、「賢者」、「盗賊」のいずれかを答えるまで待機します。プレイヤーがいずれかの単語を答えると、playerClassという変数に値が入ります。

  • ユーザーが「戦士」と答えた場合はクラスに「戦士」を設定します。
  • ユーザーが「賢者」と答えた場合はクラスに「賢者」を設定します。
  • ユーザーが「盗賊」と答えた場合はクラスに「盗賊」を設定します。

ナレーションで変数を使う

ナレーションをパーソナライズするには、*sayセクションや*repromptセクションで変数を使います。その場合、変数は波括弧({})で囲みます。以下はその例です。

@play introduction
    *say
        ミステリアスワールドへようこそ。あなたのクラスは{playerClass}です。

プレイヤーがフレーズを聞くときには、{playerClass}が変数の値で置き換えられています。

ゲームロジックで変数を使う

変数を使って、ゲームの動作を制御します。

@play introduction
    *say
        ミステリアスワールドへようこそ。あなたのクラスは{playerClass}です。
    *then
        if playerClass is '賢者' {
            -> mage start
        }

        if playerClass is '戦士' {
            -> warrior start
        }

        if playerClass is '盗賊' {
            -> thief start
        }

この例では、playerClassに格納された値によって次のシーンが決まります。

変数に数字を入れ、ゲームが進むにつれて変数を操作することもできます。以下の例は、playerHealthという変数の初期値を表しています。

set playerHealth as 10

以下はこの変数の値が減る場合の例です。

@take damage
    *say
        1ダメージを受けました。
    *then
        decrease playerHealth by 1

        if playerHealth <= 0 {
            -> game over
        }

この例ではplayerHealth変数の値が減り、値が0未満になったかどうかを確認することでgameoverというシーンに遷移するかどうかをすぐに判断しています。

decreaseコマンドは、変数の値から指定した数を引くコマンドです。変数関連の指示については、その他のセクションを参照してください。

変数が宣言されていない場合、変数を評価する文はすべてfalseを返します。たとえば、playerHealthが宣言されていない場合、if playerHealth <= 0はfalseを返し、ゲームロジックはplayerHealthを正の値とみなして進みます。

プレイヤーの名前、またはAlexaのスロット値をたずねる

正確なフレーズや単語を待機するには、hear指示を使ってそれらのフレーズや単語を記述します。プレイヤーに選択肢を与えるセクションを参照してください。

プレイヤーが何を言うかを予測できなかったり、考えられる組み合わせをすべて書き出すことができないケースも考えられます。たとえば、プレイヤーの名前を知りたい場合、考えられるすべての名前を書き出すことは非現実的です。

以下は、「お名前を教えてください」とたずねる@ask player nameというシーンの例です。

@ask player name
    *say
        お名前を教えてください。
    *then
        slot playerName to 'AMAZON.FirstName'
        hear {playerName}, 私の名前は{playerName}です {
            -> next scene
        }
@next scene
    *say
        こんにちは、{playerName}さん

構造は、プレイヤーに選択肢を与えるで使ったhearコマンドに似ていますが、次のような違いがあります。

  • slot playerName to 'AMAZON.FirstName'

    slot指示はAlexaに、hearコマンドで{playerName}を使用している場合には、日本の下の名前を待機する必要があると指示しています。詳細については、ビルトインインテントとスロット値を参照してください。

  • hear {playerName}, 私の名前は{playerName}です {

    この指示はAlexaに、{playerName}そのもの、または「私の名前は」と「です」にはさまれた{playerName}を待機するよう指示しています。たとえば、プレイヤーが「私の名前はハルキです」と答えた場合、playerNameの値は「ハルキ」となります。

  • こんにちは、{playerName}さん

    保存した値をコンテンツに挿入するには波括弧を使います。たとえば、プレイヤーが@ask player nameシーン内で「私の名前はハルキです」と言った場合、プレイヤーは@next sceneから「こんにちは、ハルキさん」と聞くことになります。

よく使う別のスロットタイプに、AMAZON.NUMBERがあります。これは、プレイヤーに数字をたずねる場合に使用できます。

ビルトインスロットタイプの詳細については、スロットタイプリファレンスを参照してください。

ランダム機能を使用して、プレイヤーに代わって決定する

ゲーム内でランダムに決定を行う場合、あるいは動的コンテンツの乱数を生成する場合には、roll指示を使用できます。

roll指示は転がすサイコロの数、面の数を組み合わせた引数を1つ取り、1から最大数までの範囲で結果を返します。標準的な6面のサイコロを転がす場合はroll 1d6、2面のコインを転がす場合はroll 1d2のように記述します。1行にroll指示だけを記述する場合、結果はrollResultという特殊な変数に格納されるので、以降の行で確認できます。

以下は、ユーザーが「私の代わりに決めて」と言った場合に、ユーザーを@scene one@scene twoのいずれかにランダムに遷移させる例です。

*then
    hear 私の代わりに決めて {
        roll 1d2
            if rollResult == 1 {
            -> scene one
            }
        -> scene two
    }

再利用可能なユーティリティシーンを作成する

ゲームを通して、特定のシーンを複数回再利用することもできます。次の例を考えてみましょう。

@start
    *say
        眠っているシャチのそばをそっと通り過ぎます。
    *then
        <-> test your luck
        if lucky {
            -> walk past the orc
        }
        -> fight orc

@walk past the orc
    *say
        音を立てずにシャチの横を通って黄金でいっぱいの
        部屋に入ります。あなたの勝ちです!
    *then
        >> END

@fight orc
    *say
        つまずいてシャチを起こしてしまい、あなたは怒ったシャチに
        殺されてしまいます。ご愁傷さまでした。
    *then
        >> END

@test your luck
    *say
        運試しをしましょう。
    *then
        clear lucky
        roll 1d6
        if rollResult > 2 {
            flag lucky
        }
        -> luck result

@luck result
    *say
        結果は{rollResult}でした。
    *then
        >> RETURN

最初のシーン(@start)では、<->指示を使って@test your luckシーンに遷移し、@luck resultシーンで» RETURN指示を見つけたら戻ります。@test your luckシーンのようなユーティリティシーンを使って、ゲームの任意のポイントに運試しを追加できます。

プレイヤーがどこからでも再起動できるようにする

すべてのシーンにコマンドを追加できます。たとえば、プレイヤーがいつ「再起動」と言ってもゲームを再起動できるようにできます。以下は、グローバルなシーン@global appendと、» RESTART指示を使う方法の例です。

@global append
    *then
        hear 再起動, 最初から始めて {
            >> RESTART
        }

この例では、@global appendシーンで、ゲーム内のすべてのシーンにプレイヤーがゲームを再起動できる指示が追加されています。

ヘルプメニューを追加する

再起動の例と同様、すべてのシーンからアクセスできるヘルプメニューを追加できます。これには、@global appendシーンと» BACK指示を使います。

@global append
    *then
        hear ヘルプ {
            -> help
        }
@help
    *say
        ヘルプをどうぞ。
    *then
        >> BACK

この例では、@global appendシーンですべてのシーンに指示が追加されています。プレイヤーがヘルプをリクエストすると、指示が@helpに遷移します。helpシーンでは役に立つメッセージが再生され、>> BACK指示により前のシーンがリプレイされます。

再起動の動作を制御する

Alexaのストーリーやゲームをテストする中で、プレイヤーが一旦スキルを中断し後で戻ってきたときの動作を制御することもできます。Skill Flow Builderは、デフォルトでは、プレイヤーがスキルを終了した最後のシーンから始めようとします。@resumeシーンを作成することでこの動作を変更できます。以下の例を参照してください。

@resume
    *say
        お帰りなさい。 前回終了したところからストーリーを
        再開しますか?
    *then
        hear はい {
            >> RESUME
        }

        hear いいえ {
            -> start
        }

@resumeシーンを作成すると、プレイヤーはストーリーの再開時に、前回終了時の最後のシーンではなく、@resumeシーンに遷移します。

プレイヤーが終了、一時停止、エラーなどでスキルを終了した場合は、最後のシーンが自動的に保存されます。最後のシーンから再開するには、次の指示を使います。

>> RESUME

プレイヤーが「はい」と答えたら、ストーリーは最後のシーンから再開します。プレイヤーが「いいえ」と答えたら、ストーリーは@startシーンに遷移します。

エンディングを作成する

ゲームやストーリーは、ある時点で終了させる必要があります。

@maybe an ending
    *say
        これで終わりのようです。
    *then
        if someflag is true {
            -> keep playing
        }

        >> END

この例では、someflagというフラグtrueの場合に、Alexaはkeep playingという別のシーンに遷移します。someflagフラグがtrueでない場合は、>> ENDが実行されます。つまり、ここでゲームは終了し、次回プレイヤーが起動したときは@startシーンから開始します。