コンテンツにスキップ

YAML仕様

本プロジェクトでは、シナリオデータを標準的な YAML形式 を使用して記述します。 エディタのGUI操作だけでなく、YAMLファイルを直接編集して高度な設定を行うことも可能です。

このガイドでは、シナリオファイルの構造と、各要素の書き方を解説します。

シナリオファイル全体は、大きく分けて meta (基本情報)characters (キャラクター)locations (場所)scenes (シーン) の4つのセクションで構成されます。

meta:
id: tokyo_quest_detective_diary # シナリオID (必須)
title: "東京クエスト - 探偵日記" # タイトル (必須)
version: 1
credits: # スタッフクレジット
author: "山田太郎"
scenario_writer: "山田太郎"
characters: # キャラクター定義
- id: detective
name: "探偵"
portrait_url: "/assets/detective.png"
locations: # 場所定義
- id: shrine
name: "天照神社"
hidden_name: "???"
lat: 35.681236
lng: 139.767125
scenes: # シーン定義(ここがメイン)
- id: intro
type: story
title: "オープニング"
dialogue:
- character_id: detective
text: "ここが事件現場か。"

シナリオ全体の基本設定です。ファイルの先頭に記述します。

meta:
id: my_scenario_01 # 一意のID(半角英数推奨)
title: "不思議な冒険" # リストに表示されるタイトル
description: "短編シナリオです。"
version: 1 # バージョン管理用
password: "secret_code" # (任意)プレイ開始時に要求するパスワード
# エリア情報(検索用)
area:
prefecture: "東京都" # または "オンライン"
city: "千代田区"
estimated_play_time: 60 # 想定プレイ時間(分)
tags: ["ミステリー", "探索"] # タグ
cover_image_url: "/assets/cover.jpg" # ホーム画面表示用カバー画像
# クレジット表記 (簡易/詳細)
credits:
# 簡易表記
author: "作者名"
writer: "シナリオライター名"
# 詳細表記 (staff リスト)
staff:
- role: "企画・制作"
name: "山田太郎"
- role: "シナリオ"
names: ["鈴木一郎", "田中花子"] # 複数名
- section: "キャスト" # セクション見出し
- role: "探偵役"
name: "佐藤健"

背景色をIDで管理できます。

preset_colors:
dark:
- id: theme_blue
name: "テーマブルー"
value: "#1e3a5f"
# 使用時:
# background:
# color: theme_blue

登場人物を定義します。ここで定義したIDを、各シーンで使用します。

characters:
- id: detective # 必須: シーンから参照するID
name: "探偵" # 必須: デフォルト表示名
description: "主人公の探偵" # 任意: エディタなどに表示される説明文
portrait_url: "/url/to/img" # 任意: 立ち絵画像のURL
portrait_group_id: "detective_expressions" # 任意: 複数表情用アセットグループID
# 名前変更ルール (Advanced)
# 条件(Condition)によって表示名を変化させる設定
display_name_overrides:
- condition:
points: [{ name: "shoutai_bare", operator: ">=", value: 1 }]
display_name: "正体がバレた探偵"
> [!IMPORTANT]
> **重要: IDの整合性**
> シーン内の会話(`dialogue`)で `character_id` を指定する場合、必ずこの `characters` セクションで定義されたIDを使用してください。未定義のIDを使用すると、バリデーションエラーとなり、ゲーム内で立ち絵が表示されません。

GPS連動イベント用の座標データを定義します。

locations:
- id: spot_station # 必須: シーンから参照するID
name: "東京駅" # 到達後の表示名
hidden_name: "謎の駅" # 未到達時の表示名
secret: true # trueの場合、未到達時は一覧でも名前が隠されます
# 名前公開条件 (reveal_condition)
# 特定のシーンを見た後に名前を公開するなどの制御が可能
reveal_condition:
hasSeen: ["scene_intro"]
# 座標情報 (10進数)
lat: 35.681236
lng: 139.767125
radius: 30 # 判定半径(m)

scenes 以下に、リスト形式でシーンを記述していきます。

[!WARNING] 厳格なプロパティチェック 各シーンタイプ(story, choice, dice など)には、使用できるプロパティが決まっています(例: choice シーンには dialogue は書けません)。 定義されていないプロパティを記述すると、バリデーションで「未対応のフィールド」として警告が表示されます。不要なプロパティは削除してください。

すべてのシーンタイプで使用できる共通プロパティです。

- id: scene_01 # 必須: 一意のシーンID
type: story # 必須: シーンタイプ
title: "シーンタイトル" # 任意: 表示用タイトル
# 場所連携(GPS)
location_ref: shrine # locations で定義した場所IDを参照
# または直接座標を指定
location:
lat: 35.681236
lng: 139.767125
radius: 30
# シークレットモード
secret: true # trueの場合、未訪問時はマップ上でタイトルが隠されます
# 出現条件
condition:
hasSeen: ["intro"]
# 背景設定
background:
imageUrl: "/assets/bg.jpg"
theme: dark
# 時間・曜日条件(後述)
conditions:
valid_days: [0, 6]
# 完了時アクション
on_complete:
actions:
- type: jump_to
sceneId: next_scene_id
プロパティ説明
idstringシーンの一意識別子(必須)
typestringシーンタイプ(必須)
titlestring表示用タイトル
location_refstring場所定義への参照ID
locationobjectGPS座標(lat, lng, radius)
secretbooleantrueで未訪問時にタイトルを隠す
conditionConditionシーン出現条件
conditionsSceneConditions時間・曜日条件
backgroundobject背景設定
on_completeActionBlock完了時アクション
allow_backboolean戻るボタンの表示(choice/keyword_input用、デフォルト: true)

最も基本的な会話シーンです。

- id: scene_01
type: story
title: "冒頭"
# 背景設定
background:
imageUrl: "/assets/bg_01.jpg" # または color
theme: dark
# 会話データ
dialogue:
- character_id: detective # 定義済みキャラ
text: "こんにちは。"
- speaker: "謎の声" # 未定義キャラ(名前直接指定)
text: "誰だ?"
- narrator: "静寂が包んだ。" # ナレーション(枠なし表示)
# 複数行テキスト (|)
# 改行は「ページ送り(タップ待ち)」として扱われます
- character_id: detective
text: |
実は…お話ししていないことが
もう一つあるんです。
# 立ち絵・表示名の一時変更(表情差分など)
- character_id: detective
text: "驚いたな!"
portrait_override: "/assets/detective_surprised.png"
display_name_override: "驚く探偵"
# ボイス再生 (Voice) (任意)
- character_id: detective
text: "犯人はお前だ!"
voice: "/assets/voice/det_01.mp3"
# 効果音 (Sound Event)
- type: sound
src: "/assets/se/bang.mp3"
volume: 1.0 # 0.0 ~ 1.0 (デフォルト: 1.0)
wait: true # 再生終了まで待機するか (デフォルト: false)
# 演出 (Effect)
- character_id: detective
text: "うわっ!"
effect:
type: "shakeX" # animate.cssのアニメーション名
target: "character" # character (立ち絵) / screen (画面全体)
duration: 500 # ms (省略可)
wait: true # アニメーション終了まで操作不能にするか (省略可)
# 条件付き表示 (Condition)
# 特定の条件を満たす場合のみ表示されます
- character_id: detective
text: "よくぞ謎を解いたな!"
condition:
points: [{ name: "intelligence", operator: ">=", value: 10 }]
# 完了時のアクション
on_complete:
actions:
# シーン移動 (Jump)
- type: jump_to
sceneId: scene_02
# ポイント変数の操作 (Point Modify)
- type: point_modify
point: { name: "kizuna", amount: 1, operator: "add" } # kizuna に +1 (addは省略可)
# 条件付きアクション(IF-DO)
- type: jump_to
sceneId: scene_secret
condition:
points: [{ name: "kizuna", operator: ">=", value: 5 }]

アイテムを獲得するイベントです。

- id: get_key
type: item
title: "鍵の入手"
# アイテム設定
item_name: "古びた鍵"
item_description: "錆びついている。"
item_image: "/assets/items/key.png"
background:
imageUrl: "/assets/room.jpg"
on_complete:
# アイテム入手フラグ(変わりに変数を使用)
actions:
- type: point_modify
point: { name: "has_key", amount: 1 }
- type: jump_to
sceneId: scene_after

分岐を作成します。

- id: branch_01
type: choice
title: "運命の選択"
prompt: "どちらへ進みますか?"
choices: # 最大6つまで記述可能
- id: choice_a
text: "右の道"
on_select:
actions:
- type: point_modify
point: { name: "bravery", amount: 10 }
- type: jump_to
sceneId: scene_right
- id: choice_b
text: "左の道"
on_select:
actions:
- type: jump_to
sceneId: scene_left
> [!NOTE]
> **選択肢の記述ルール**
> - 表示名には `label` ではなく **`text`** を使用してください。
> - 遷移先は `next_scene` ではなく、**`on_select`** 内の `actions`(`jump_to`)で指定してください。
> 古い形式(`label`, `next_scene`)を使用すると警告が表示されます。
#### 戻るボタン
選択肢シーンでは、デフォルトで「戻る」ボタンが表示されます。プレイヤーは前のシーンに戻って情報を確認してから選択できます。
```yaml
- id: no_return_choice
type: choice
title: "最後の決断"
prompt: "もう引き返せない..."
allow_back: false # 戻るボタンを非表示にする
choices:
- id: proceed
text: "覚悟を決める"
on_select:
actions:
- type: jump_to
sceneId: ending

文字入力を求めます。

- id: puzzle_01
type: keyword_input
prompt: "合言葉を入力せよ"
answers:
- keyword: "ひらけごま"
match_type: exact # exact(完全一致) / contains(部分一致) / normalize(ゆらぎ吸収) / regex
on_correct:
actions:
- type: jump_to
sceneId: scene_success
# ヒント(任意)
hints:
- after_attempts: 3
text: "「ひ」から始まります"
# 不正解時の反応(任意)
on_wrong:
dialogue:
- character_id: detective
text: "違うようだ…。"

謎解きシーンでも、デフォルトで「戻る」ボタンが表示されます。プレイヤーはヒントを探しに前のシーンへ戻ることができます。

- id: final_puzzle
type: keyword_input
prompt: "最後の謎を解け"
allow_back: false # 戻れない緊迫感を演出
answers:
- keyword: "答え"
match_type: exact
on_correct:
actions:
- type: jump_to
sceneId: ending

ダイスを振って、出目に応じた分岐を行います。

- id: check_strength
type: dice
title: "扉のこじ開け"
text: "重い扉だ。筋力でこじ開けよう。(目標: 7以上)"
# ダイス設定
dice:
sides: 6 # 何面ダイスか (6, 10, 20, 100...)
count: 2 #振る個数 (2d6)
modifier: # 補正値 (任意)
variable: "str" # 変数 'str' の値を加算
scale: 1 # 倍率 (デフォルト: 1)
constant: 0 # 固定値 (デフォルト: 0)
# キャラクター表示 (任意)
character_image: "/assets/chars/warrior.png"
# 結果の保存 (任意)
variable: "last_roll_result"
# 判定ルール (上から順に評価)
results:
- label: "クリティカル!"
range: [12, 12] # 12のみ (2d6の最大値)
on_match:
actions:
- type: point_modify
point: { name: "exp", amount: 50 }
- type: jump_to
sceneId: scene_critical
- label: "成功"
range: [7, 11] # 7以上、11以下
on_match:
actions:
- type: jump_to
sceneId: scene_success
- label: "失敗"
range: [null, 6] # 6以下 (最小値なし)
on_match:
actions:
- type: jump_to
sceneId: scene_fail

5.5 時間・曜日条件 (Scene Conditions)

Section titled “5.5 時間・曜日条件 (Scene Conditions)”

シーンごとに、日時・曜日などの条件を設定できます。条件を満たさない場合、そのシーンは無効化されます(選択肢として表示されない、次のシーンとして遷移しないなど)。タイマー機能は start_timer アクションとして別途実装されています。

- id: summer_event
type: story
title: "夏祭りイベント"
# 時間・環境条件
conditions:
# 有効期間(日付)
valid_period:
start: "2025-08-01" # YYYY-MM-DD形式
end: "2025-08-31"
# 有効時間帯
valid_time:
start: "17:00" # HH:MM形式
end: "21:00"
# 有効曜日 (0=日, 1=月, 2=火, 3=水, 4=木, 5=金, 6=土)
valid_days: [5, 6] # 金・土曜日のみ
dialogue:
- narrator: "夏祭りの賑わいが聞こえてくる..."

カウントダウンタイマーを開始し、時間切れ時に特定のアクションを実行できます。タイムリミット付きの謎解きや脱出ゲームに活用できます。

- id: timer_start
type: story
title: "爆弾発見!"
dialogue:
- narrator: "時限爆弾が起動した!解除まで3分しかない!"
on_complete:
actions:
- type: jump_to
sceneId: bomb_puzzle
- id: bomb_puzzle
type: choice
title: "爆弾解除"
prompt: "どのコードを切断する?"
choices:
- id: red
text: "赤いコード"
on_select:
actions:
- type: jump_to
sceneId: defused
- id: blue
text: "青いコード"
on_select:
actions:
- type: jump_to
sceneId: explosion

start_timer アクションの詳細:

タイマーは on_complete のアクションとして start_timer を使用して開始します。

on_complete:
actions:
- type: start_timer
timer:
duration: 3 # 制限時間(分)
on_timeout: # タイムアウト時のアクション
actions:
- type: jump_to
sceneId: explosion
- type: jump_to
sceneId: bomb_puzzle
プロパティ説明
durationnumber制限時間(分)
on_timeoutActionBlockタイムアウト時に実行するアクション

cancel_timer アクションの詳細:

タイマーを途中で停止するには cancel_timer アクションを使用します。 これにより、爆弾解除などの「間に合った」演出が実現できます。

# 爆弾解除成功シーン
- id: scene_defuse_success
type: story
dialogue:
- narrator: "間に合った! 爆弾を解除した。"
on_complete:
actions:
- type: cancel_timer # 実行中のタイマーをすべて停止
- type: jump_to
sceneId: ending_success

valid_time は跨日(深夜営業など)にも対応しています。終了時刻が開始時刻より早い場合、翌日までの時間帯として解釈されます。

start: "22:00"
end: "05:00" # 22:00〜翌05:00まで有効

5.6 テキストへの変数の埋め込み (Variable Substitution)

Section titled “5.6 テキストへの変数の埋め込み (Variable Substitution)”

テキスト(会話文、選択肢、ダイス説明文など)の中に {変数名} と記述することで、現在保持している変数の数値を動的に表示することができます。

- id: check_status
type: story
title: "詳細確認"
dialogue:
- character_id: narrator
text: |
現在の所持金は {money} 円、
攻撃力は {attack_power} です。

利用可能な箇所:

  • ストーリーシーンの text / narrator
  • 選択肢シーンの prompt および選択肢の text
  • ダイスシーンの text

※ 未定義の変数を指定した場合、undefined と表示されるか、変換されずにそのまま表示される場合があります。


6. 条件判定 (Condition) と アクション (Actions)

Section titled “6. 条件判定 (Condition) と アクション (Actions)”

従来の「フラグ」システムに代わり、より柔軟な「条件判定オブジェクト」と「アクションリスト」が導入されました。

シーンの出現条件(condition)や、各アクションの実行条件で使用します。

主な判定要素:

  1. 既読判定 (hasSeen / hasNotSeen)
    • 特定のシーンIDを既に見たか(または見ていないか)を判定します。
  2. 選択履歴 (hasChosen)
    • 特定の選択肢を選んだことがあるかを判定します。
  3. ポイント変数 (points)
    • 任意の数値変数の値を比較します。
  4. 既読カウント (seenCount)
    • 複数のシーンのうち、指定数を既読済みかどうかを判定します。
  5. 直前のシーン (lastSceneId)
    • 直前に訪問したシーンIDを判定します。
- id: secret_event
type: story
# このシーンが発生するための条件
condition:
# シーンAを見たことがある、かつ、シーンBを見ていない
hasSeen: ["scene_A"]
hasNotSeen: ["scene_B"]
# かつ、ポイント「kendo」が 5 以上
points:
- name: "kendo"
operator: ">="
value: 5

複数のシーンのうち、一定数を既に見たかどうかを判定します。

- id: unlock_bonus
type: story
condition:
# 5つのシーンのうち、3つ以上を既読
seenCount:
targets: ["scene_A", "scene_B", "scene_C", "scene_D", "scene_E"]
count: 3
operator: ">=" # ">=" / "==" / "<="

プレイヤーが直前に訪問したシーンを条件にできます。

- id: caught_in_the_act
type: story
# 「forbidden_room」から直接来た場合のみ発生
condition:
lastSceneId: forbidden_room
dialogue:
- character_id: guard
text: "何をしている!侵入者だ!"

on_completeon_selectactions リストで実行する内容を記述します。

  1. point_modify: 変数の加算・減算・設定
  2. jump_to: シーン移動
  3. game_clear: ゲームクリア処理
  4. next_hint: 次のヒントを表示
  5. start_timer: カウントダウンタイマーを開始
  6. cancel_timer: 実行中のタイマーを停止

ポイント操作の拡張 (operator): point_modify では operator を指定することで、加算以外にも値を直接セットすることが可能です。

  • add: 加算(デフォルト)
  • set: 上書き
actions:
# 加算(通常)
- type: point_modify
point: { name: "score", amount: 100 }
# 値のセット(リセットなど)
- type: point_modify
point: { name: "mode_flag", amount: 1, operator: "set" }
- type: jump_to
sceneId: scene_good_ending
# アクション自体に条件をつけることも可能(IF-DO)
condition:
points: [{ name: "score", operator: ">=", value: 1000 }]

ゲームクリアアクション (game_clear)

Section titled “ゲームクリアアクション (game_clear)”

ゲームの終了処理を行います。クリア画面のボタンの挙動を設定できます。

プロパティ説明
labelstringクリア画面のボタンに表示するテキスト(例:「タイトルへ戻る」)
next_actionstringボタンを押した後の挙動。back_to_top (トップへ) または open_url (外部サイトへ)
urlstringnext_action: open_url の場合の遷移先URL
actions:
- type: game_clear
game_clear:
label: "アンケートに答える"
next_action: open_url
url: "https://example.com/survey"