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
ブロック内に->
指示がある場合、現在のシーンに指定された残りの指示は実行されず、すぐに遷移が行われます。以下は、「...でない」(!
)記号をif
文内で使用する方法の例です。これらの例は論理的には同じであり、プレイヤーのエクスペリエンスも同じになります。
バージョン1:
@escape room
*say
あなたは今部屋の中にいます。
*then
if skeletonkey {
-> open door
}
-> door locked
バージョン2:
@escape room
*say
あなたは今部屋の中にいます。
*then
if !skeletonkey {
-> door locked
}
-> open door
以下は、if
指示内に指定されたflag
やunflag
など、複数の指示を実行する方法の例です。これは、何でも開けられる鍵がゲーム内で1回しか使えないアイテムの場合に便利です。
*then
if skeletonkey {
unflag skeletonkey
-> open door
}
複数のフラグをチェックする
and
やor
を使って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
シーンから開始します。