ビヘイビアと自動化
プラットフォーム上のほとんどのワールドはルールを一切使っていません。それでまったく構いません。ルールは少数派のツールです — クリエイターがそれを手にするのは、AIに一貫性が期待できない、ごく特定のジョブが手元にあるときです。
このガイドではルールが価値を持つ場面、得意なこと、構築方法を解説します。トリガー、条件、アクションの基本については はじめに:自動化 を参照してください。
ルールが価値を持つ場合(持たない場合)
ルールに関して新規クリエイターが最もよくやるミスは、過剰設計です。エディタのビヘイビアセクションを見て「何でも自動化すべき」と思ってしまいます。そして30個のルールを構築し、よく書かれたエントリがすでに扱っていることを複製してしまい、ワールドが生き生きとせず機械的になります。
ルールは精密性のためにあります。 AIの不一致が体験を壊すような問題を解決します。
| 問題 | なぜルールで解決するか |
|---|---|
| 「親密度がちょうど75になったらプレイヤーに通知すべき」 | AIは正確な数字を知らない — エンジンは知っている |
| 「アリーナに入ったらバトルミュージックに切り替え」 | AIは半分はオーディオディレクティブを忘れる |
| 「3ターンごとに空腹度を増加」 | AIは時々ターン2でやり、時々完全に忘れる |
| 「HPが0になった瞬間にデス画面が出るべき」 | AIが一度でも間違えると致命的 |
エントリは物語のためにあります。 柔軟性とニュアンスが重要な問題を解決します。
| 問題 | なぜエントリで解決するか |
|---|---|
| 「信頼が育つにつれてNPCの話し方を変える」 | 条件付きエントリはAIに行動指針を与え、硬直したスクリプトを与えない |
| 「プレイヤーがロケーションを訪れたら伝承を明かす」 | キーワードトリガーのエントリはAIのコンテキストに自然に流れ込む |
| 「ダンジョンに入ったらトーンを変える」 | エントリは雰囲気を描写する。ルールはディレクティブを注入するだけ |
経験則: ルールの inject-directive アクションに物語テキストの段落を書いているなら、おそらくエントリを書くべきです。ルールはスイッチとダイヤル。エントリは実際のコンテンツです。
Sakura Seasonがどう両方を使っているか
Sakura Seasonはルールとエントリが共に働く最良の例です。9つのルールがあり — すべて同じ基本ジョブを行っています:親密度しきい値を監視。
エントリ は各ヒロインが異なる親密度レベル(警戒、打ち解け、弱さを見せる)でどう振る舞うかを描写します。ルール は精確な瞬間を扱います:25での通知(「You've caught Hina's attention...」のような)、50で矛盾するプッシュ・プル行動を書くようAIに伝えるディレクティブの注入、75での告白アークをトリガーする実績トースト。
エントリが重い仕事をします。ルールはマイルストーンをきっかり正しい瞬間に着地させます。
トリガー型を深く
トリガーはエンジンが いつ このビヘイビアをチェックするかを決定します。異なる種類の目覚まし時計のようなものと思ってください。
実際によく使うもの
変数がしきい値を超える (variable-crossed) — 最も人気のトリガーで理由があります。number変数が特定の線を超える その瞬間 に発火します。
これは毎ターン「healthは20未満か?」をチェックするのとは違います。crossedトリガーは値が実際にしきい値を 横切る ときに 一度だけ 発火します。healthが既に10で10のままなら、再発火しません。
設定するのは3つ:どの変数、どのしきい値、どの方向(rises-above または drops-below)。
Wandering Diaryはこれを3つ使ってリージョン切り替えを実装:distance 変数が50を超えると郡へ入り、150で山、200で省都。各しきい値が新しい region 変数をセットし通知を表示します。
状態変化 (state-change) — 最も広いトリガー。任意の 変数が変わるたびに発火します。条件と組み合わせて関心事を絞り込みましょう。
これはしきい値の超過ではなく、変数が特定の値を持つことに反応したいときに使います。例:「状態が変化するたび、locationが dark_forest かをチェックし、そうなら不気味な音楽を再生」。何が変化を引き起こしたとしても、ルールが再チェックするので、ロケーション変化を見逃しません。
Nターンごと (turn-count) — スケジュールで発火します。everyNTurns: 3 でターン3、6、9、12…に発火。atTurn: 10 で特定ターンの単発。
サバイバルメカニクス(空腹度の増加)、ペース調整イベント(ターン20で時間切れ警告)、定期リマインダーに適します。
毎ターン (every-turn) — プレイヤー/AIの往復ごとに発火します。慎重に使ってください — 毎ターン何か可視のことを行うルールはプレイヤーを苛立たせます。ほとんどのターンをフィルタする条件付きで使うか、サイレントなバックグラウンド処理用にしましょう。
セッション開始 (session-start) — 新会話の開始時に1度だけ発火。初期化に良い:開始値の設定、ようこそメッセージ表示、オープニングミュージック再生。
あまり使われないトリガー
プレイヤーキーワード (keyword) — プレイヤーのメッセージが特定のワードを含むと発火。ロアブックのキーワードと同じマッチオプション:オプションのwhole-wordマッチング、正規表現(キーワードが /.../flags のとき)、セカンダリキーワードフィルタ(AND_ANY、AND_ALL、NOT_ANY、NOT_ALL)。
AIキーワード (ai-keyword) — 上と同じだがAIの応答をスキャン。AIが書いたことに反応するのに有用、例「AIが 'battle begins' と書いたら音楽切り替え」。
手動 (manual) — カスタムコンポーネントから api.executeAction() で明示的に呼ばれた時のみ発火。ボタン押下でゲームロジックを起動するカスタムUIのワールド用。
アクション (action) — 特定のカスタムアクションボタンが押されたときに発火。
一定間隔でのスケジューリング
ビヘイビアセクションに実時間のタイマーはありません——ペースは秒ではなくターンで測ります。周期的なものには N ターンごと トリガーを使ってください:第 N、2N、3N…… ターンで発火します(5 に設定すると第 5、10、15 ターンで発火)。生存値の減少、維持コスト、繰り返しのリマインダー——タイマーが担うはずの仕事はこれでカバーできます。
条件:ONLY IFチェック
ルールはエントリと同じ条件システムを使います — 同じ7演算子(eq、neq、gt、gte、lt、lte、contains)と同じAll/Any結合ロジック。完全な演算子リファレンスは 優れたエントリの書き方:状態駆動エントリ を参照してください。
条件を空のままにすると、ルールはトリガーがマッチするたびに発火します。
ある変数を別の変数と比べる
デフォルトでは、条件は変数を固定の数値や単語と比べます——「好感度 ≥ 50」。しかし右辺には 定数 / 変数 トグルがあります。変数 に切り替えると、条件は2つのライブ変数を比較するようになります:
好感度 > 警戒心—— 好感度が今まさに警戒心を上回っている間だけ発火所持金 >= 価格—— 価格をハードコードせずに「買えるか」をチェック
しきい値そのものが固定ではなく、ゲームとともに動く場合にこれを使います。同じ仕組みにあと2つ:
- 左辺は JSON 変数へのドットパスを受け付けます:
インベントリ.所持金 >= 100。 containsは部分文字列に加えて 配列メンバーシップ にもマッチします。フラグがその要素を含むリストならフラグ contains "王に会った"は真になります。
アクション型:ルールができること
条件が通ると、エンジンはアクションを順に実行します。1つのルールに複数アクションを含められます — ここがルールが強力になる場所です。
変数を修正
ゲーム状態変数を直接変更。9操作:set、add、subtract、multiply、toggle、append、merge、push、delete。
最も一般的:set(値を上書き)、add/subtract(数値の増減)、toggle(ブール反転)。
オペランドにも同じ 定数 / 変数 トグルがあります。変数 に切り替えると、別の変数の現在値をその操作に流し込めます——生命 -= 力、スコア += コンボ、財布 += 日収。エンジンはルールが発火した瞬間に参照先の変数を読むので、計算は常にライブ値を使い、手で同期する数値は要りません。
ディレクティブを注入
AIのプロンプトに一時的な指示を追加。これはおそらく最も強力なアクションです。なぜならAIが 指示されたこと を変えるため、物語の方向全体が変わるからです。
ユニークなID(後で削除できるよう)、指示テキスト、プロンプト内の配置(top、before_char、after_char、bottom、depth、auto)を指定します。
デフォルトでは注入されたディレクティブはターン間で持続します(persistent: true)。duration を設定してNターン後に自動失効させることもできます。
Sakura Seasonは各ヒロインの親密度50でこれを使います。Rinが50に達するとルールが注入:「Rinの親密度が深い段階に入った。氷が割れ始める。委員会で不必要なことを言い、屋上で読んでいた本について無意識に意見を共有し、その後突然黙る。」 AIはそれ以降毎ターンこれを読み、その描写を自然にシフトします。
ディレクティブを削除
以前に注入したディレクティブを削除。注入時の同じ directiveId で参照します。
コンテキストを送信
AIに不可視のメッセージを送り応答をトリガー。プレイヤーはこのメッセージを見ませんが、AIはそれを読み、それに応じて応答します。物語のビートを強制するのに便利:「モンスター登場! ランダムエンカウントを描写」。
エントリをトグル
ロアブックエントリをIDで有効/無効にします。toggle-entry で enabled: true をアクティブにするルールは、適切な瞬間に隠れた伝承を明かすことができます。
ルールをトグル
別のビヘイビアを有効/無効。連鎖を構築する鍵:ルールAがダンジョンに入ったときにアクティブになり、ルールB(毎ターンのモンスターエンカウンタ)を有効化。ルールCがダンジョンから出るとアクティブになりルールBを無効化。
プレイヤーに通知
トースト通知をポップアップ。4スタイル:
| スタイル | 見た目 | 適した用途 |
|---|---|---|
info | 青 | 中立的な更新(「新リージョンに入った」) |
achievement | 金 | マイルストーンとアンロック |
warning | 黄 | 注意(「補給が尽きてきた」) |
danger | 赤 | 重大警告(「あなたは倒れた」) |
オーディオを再生
BGMと効果音を制御。trackId(オーディオ設定のトラックに一致)、action(play、stop、crossfade、volume)、オプションの volume と fadeDuration を取ります。
公開ワールドの実例パターン
親密度しきい値(Sakura Season)
定番のユースケース。Sakura Seasonには3ヒロインに9ルールあり、それぞれ同じ3層パターンに従います。
親密度25で — 控えめなinfo通知。「Hinaの注意を引いたようだ...」と story_phase を "daily" にセット。単発(maxFireCount: 1)。
親密度50で — achievement通知。「Hinaがあなたを特別な存在として見始めている...」プラス矛盾するプッシュ・プル行動を描写するディレクティブを注入、story_phase を "deepening" にセット。単発。
親密度75で — クライマックストリガー。Achievement通知、告白シーンをアレンジするディレクティブ、story_phase を "climax"。単発。
パターンに注目:すべてのルールは variable-crossed + rises-above を使い、ちょうど1回発火し、プレイヤー通知+AIディレクティブ+フェーズ変数更新を組み合わせます。3つのアクション型が連携して1つの意味ある瞬間を作ります。
リージョン切り替え(Wandering Diary)
Wandering Diaryはプレイヤーが旅するにつれて増加する distance 変数を追跡します。3つの variable-crossed ルールが距離50、150、200で region 変数を切り替え、それぞれ通知を表示:「ついに荒野を離れ郡の領域に入った」「郡を抜けて果てしない山脈が広がる」「遠くに省都の輪郭が現れる」。
これによりAIが距離を追跡したりリージョン境界を覚えたりすることなく、シームレスな旅の進行が生まれます。
デストリガー
Wandering Diaryとサバイバルキットテンプレートの両方が同じパターンを使います:variable-crossed で healthが1未満に落下、dangerスタイル通知。重要な詳細:
- Priority 100 — 死は何より先に評価されるべき
- maxFireCount: 1 — 死通知は1回だけ発火(ゼロを2度下回ることはないので大抵のワールドはこれを気にしませんが)
- 時々
inject-directiveと組み合わせ、AIにキャラクターの最期を描写するよう伝える
ダンジョン起動連鎖
RPGワールドの共通パターン:ルールAがダンジョンへの入場を聞き(キーワードトリガーまたは state-change + 条件)、toggle-rule でルールB(クールダウン付き every-turn のモンスターエンカウンタ)をアクティブ化。3つ目のルールが退出を聞きルールBを非アクティブ化。
これによりAIがダンジョン内かどうかを追跡することなくモンスターエンカウンタを特定エリアに限定できます。
エンジンがルールを処理する方法
各プレイヤーメッセージ、AI返信、状態変化の後、エンジンは1パスですべてのビヘイビアを実行:priorityでソート(高い順)、各々を順にチェック。各ビヘイビアについて尋ねる:有効か? トリガー型がこのイベントに合うか? トリガーの具体内容が合うか(キーワード発見、しきい値超過など)? 条件が通るか? クールダウン中か? max fire countを超えたか? すべて通ればアクションが収集される。すべてのビヘイビアがチェックされた後、収集アクションが順番に実行。それらが変数を変えると、エンジンは再評価する場合がある(無限ループ防止の深度制限あり)。
プロセス全体はプレイヤーに不可視 — 彼らは結果だけを見ます:通知、音楽の変化、変数更新。
ルール発火の制御
Priority(優先度)
数値が大きいほど先に評価されます。複数ルールが同時にトリガーされた場合、優先度が順序を決めます。
実用ガイド:デスチェックは100、ストーリーマイルストーンは50、雰囲気効果は10〜20。精密である必要はなく、重要なルールがあれば良いものより先に走るようにするだけです。
Cooldown(クールダウン)
発火後、ルールはこのターン数だけ眠ります。cooldownTurns: 5 の空腹警告は毎ターンプレイヤーを煩わせず、警告間に少なくとも5ターン空きます。
Max fire count(最大発火回数)
ルールは生涯で最大この回数まで発火可能。maxFireCount: 1 で単発イベント — 実績、初回チュートリアル、ストーリーマイルストーンに最適。
有効/無効状態
ルールはデフォルトで有効ですが、enabled: false を設定して別のルールが toggle-rule で有効化するまで休眠状態にすることもできます。これが上述したダンジョン起動パターンの基礎です。
よくあるミス
エントリで済むのにルールで過剰設計。 inject-directive アクション内に長い物語テキストを書いている自分に気付いたら、おそらく条件付きエントリが欲しいのです。ルールは1〜2文のガイダンスを注入。エントリは段落のコンテキストを提供。
variable-crossed のつもりで state-change を使う。 state-change は 任意の 変数が変わるたびに発火。「healthが20未満になったら通知」が欲しいなら variable-crossed を使ってください — 横切る瞬間に1回発火します。state-change + health < 20 をチェックする条件だと、healthが20未満の間、その後の状態変化のたびに 発火し、それは恐らく望むものではないでしょう。
頻繁なトリガーでクールダウンを忘れる。 クールダウンなしの every-turn ルールは毎ターン発火します。通知を表示するならプレイヤーはスパムされます。常に問いましょう:「これをプレイヤーが実際にどれだけの頻度で見るべきか?」
3つで済むワールドに30個のルールを作る。 Sakura Seasonを見てください:9ルール、3ヒロイン、各3しきい値。深いメカニクスを持つワールドです。ほとんどのワールドはもっと少なくて済み、多くの人気作は0で出荷されます。エントリと変数から始めましょう。AIが特定のことに一貫しないと気付いたときだけルールを追加してください。
しきい値をテストしない。 health < 10 でルールが発火するが、AIが実際にhealthをそこまで下げない(「healthが30未満なら負傷したと描写」とエントリで指示しているため)なら、ルールは決してトリガーしません。しきい値がワールドの実際の動作と整合することを確認してください。
関連項目
- 優れたエントリの書き方 — 物語的変化には条件付きエントリの方が適することが多い
- オーディオ設計 —
play-audioアクションと、ルール vs AIディレクティブの使い分け - ゲーム状態の設計 — ルールが反応する変数の設計
完全なルールスキーマと評価パイプライン → World Spec:ルールとリアクション
