コンテンツにスキップ

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 # バージョン管理用
# エリア情報(検索用)
area:
prefecture: "東京都" # または "オンライン"
city: "千代田区"
estimated_play_time: 60 # 想定プレイ時間(分)
tags: ["ミステリー", "探索"] # タグ
cover_image_url: "/assets/cover.jpg" # ホーム画面表示用カバー画像
# クレジット表記
credits:
author: "作者名"
writer: "シナリオライター名" # scenario_writer でも可
artists: ["イラストレーター1"] # 複数可
music: "作曲者名"
others:
special_thanks: "任意の追加情報"

背景色を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: "正体がバレた探偵"

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 以下に、リスト形式でシーンを記述していきます。

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

- 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:
next_scene: next_scene_id
プロパティ説明
idstringシーンの一意識別子(必須)
typestringシーンタイプ(必須)
titlestring表示用タイトル
location_refstring場所定義への参照ID
locationobjectGPS座標(lat, lng, radius)
secretbooleantrueで未訪問時にタイトルを隠す
conditionConditionシーン出現条件
conditionsSceneConditions時間・曜日条件
backgroundobject背景設定
on_completeActionBlock完了時アクション
rulesRule[]条件分岐ロジック

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

- 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: "驚く探偵"
# 完了時のアクション
on_complete:
next_scene: scene_02 # 次のシーンID (省略可)
# 詳細なアクションリスト
actions:
# ポイント変数の操作
- type: point_modify
point: { name: "kizuna", amount: 1 } # kizuna に +1
# 条件付きアクション(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 }
next_scene: scene_after

分岐を作成します。

- id: branch_01
type: choice
title: "運命の選択"
prompt: "どちらへ進みますか?"
choices: # 最大6つまで記述可能
- id: choice_a
text: "右の道"
on_select:
next_scene: scene_right
actions:
- type: point_modify
point: { name: "bravery", amount: 10 }
- id: choice_b
text: "左の道"
on_select:
next_scene: scene_left

文字入力を求めます。

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

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

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

シーンごとに、日時・曜日・経過時間などの条件を設定できます。条件を満たさない場合、そのシーンは無効化されます(選択肢として表示されない、次のシーンとして遷移しないなど)。

- 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:
next_scene: bomb_puzzle
- id: bomb_puzzle
type: choice
title: "爆弾解除"
# このシーンは timer_start を訪問してから3分以内のみ有効
conditions:
elapsed_time:
trigger_scene_id: timer_start # 計測開始シーンID
max_minutes: 3 # 最大経過時間(分)
# タイムアウト時のアクション(任意)
on_timeout:
next_scene: explosion
actions:
- type: point_modify
point: { name: "failed", amount: 1 }
prompt: "どのコードを切断する?"
choices:
- id: red
text: "赤いコード"
on_select:
next_scene: defused
- id: blue
text: "青いコード"
on_select:
next_scene: explosion

elapsed_time の詳細:

プロパティ説明
trigger_scene_idstring計測開始となるシーンID
min_minutesnumber最小経過時間(この時間が経過するまで無効)
max_minutesnumber最大経過時間(この時間を超えると無効)
on_timeoutActionBlockタイムアウト時に実行するアクション

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

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

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: 次のヒントを表示
actions:
- type: point_modify
point: { name: "score", amount: 100 }
- type: jump_to
sceneId: scene_good_ending
# アクション自体に条件をつけることも可能(IF-DO)
condition:
points: [{ name: "score", operator: ">=", value: 1000 }]

シーン開始時などに、複数の条件分岐をまとめて記述する場合 rules を使用します。 on_complete はシーン終了時の動作ですが、rules は条件に応じたアクションの分岐ロジックを定義します(※ツール上のサポート状況により、実装が推奨される箇所が異なりますが、YAMLとしては定義可能です)。

rules:
- if:
hasSeen: ["bad_end_trigger"]
do:
- type: game_clear
gameClear:
nextAction: back_to_top
label: "BAD END"